dm: mmc: Add support for driver-model block devices
Add support for enabling CONFIG_BLK with MMC. This involves changing a few functions to use struct udevice and adding a MMC block device driver. Signed-off-by: Simon Glass <sjg@chromium.org>
This commit is contained in:
parent
ad27dd5e13
commit
33fb211dd2
|
|
@ -216,9 +216,17 @@ static int mmc_read_blocks(struct mmc *mmc, void *dst, lbaint_t start,
|
||||||
return blkcnt;
|
return blkcnt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_BLK
|
||||||
|
static ulong mmc_bread(struct udevice *dev, lbaint_t start, lbaint_t blkcnt,
|
||||||
|
void *dst)
|
||||||
|
#else
|
||||||
static ulong mmc_bread(struct blk_desc *block_dev, lbaint_t start,
|
static ulong mmc_bread(struct blk_desc *block_dev, lbaint_t start,
|
||||||
lbaint_t blkcnt, void *dst)
|
lbaint_t blkcnt, void *dst)
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
|
#ifdef CONFIG_BLK
|
||||||
|
struct blk_desc *block_dev = dev_get_uclass_platdata(dev);
|
||||||
|
#endif
|
||||||
int dev_num = block_dev->devnum;
|
int dev_num = block_dev->devnum;
|
||||||
int err;
|
int err;
|
||||||
lbaint_t cur, blocks_todo = blkcnt;
|
lbaint_t cur, blocks_todo = blkcnt;
|
||||||
|
|
@ -580,6 +588,27 @@ static int mmc_switch_part(struct mmc *mmc, unsigned int part_num)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_BLK
|
||||||
|
static int mmc_select_hwpart(struct udevice *bdev, int hwpart)
|
||||||
|
{
|
||||||
|
struct udevice *mmc_dev = dev_get_parent(bdev);
|
||||||
|
struct mmc *mmc = mmc_get_mmc_dev(mmc_dev);
|
||||||
|
struct blk_desc *desc = dev_get_uclass_platdata(bdev);
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (desc->hwpart == hwpart)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (mmc->part_config == MMCPART_NOAVAILABLE)
|
||||||
|
return -EMEDIUMTYPE;
|
||||||
|
|
||||||
|
ret = mmc_switch_part(mmc, hwpart);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#else
|
||||||
static int mmc_select_hwpartp(struct blk_desc *desc, int hwpart)
|
static int mmc_select_hwpartp(struct blk_desc *desc, int hwpart)
|
||||||
{
|
{
|
||||||
struct mmc *mmc = find_mmc_device(desc->devnum);
|
struct mmc *mmc = find_mmc_device(desc->devnum);
|
||||||
|
|
@ -600,27 +629,7 @@ static int mmc_select_hwpartp(struct blk_desc *desc, int hwpart)
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
int mmc_select_hwpart(int dev_num, int hwpart)
|
|
||||||
{
|
|
||||||
struct mmc *mmc = find_mmc_device(dev_num);
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
if (!mmc)
|
|
||||||
return -ENODEV;
|
|
||||||
|
|
||||||
if (mmc->block_dev.hwpart == hwpart)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
if (mmc->part_config == MMCPART_NOAVAILABLE)
|
|
||||||
return -EMEDIUMTYPE;
|
|
||||||
|
|
||||||
ret = mmc_switch_part(mmc, hwpart);
|
|
||||||
if (ret)
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int mmc_hwpart_config(struct mmc *mmc,
|
int mmc_hwpart_config(struct mmc *mmc,
|
||||||
const struct mmc_hwpart_conf *conf,
|
const struct mmc_hwpart_conf *conf,
|
||||||
|
|
@ -1554,7 +1563,6 @@ int mmc_bind(struct udevice *dev, struct mmc *mmc, const struct mmc_config *cfg)
|
||||||
mmc->dsr_imp = 0;
|
mmc->dsr_imp = 0;
|
||||||
mmc->dsr = 0xffffffff;
|
mmc->dsr = 0xffffffff;
|
||||||
/* Setup the universal parts of the block interface just once */
|
/* Setup the universal parts of the block interface just once */
|
||||||
bdesc->if_type = IF_TYPE_MMC;
|
|
||||||
bdesc->removable = 1;
|
bdesc->removable = 1;
|
||||||
|
|
||||||
/* setup initial part type */
|
/* setup initial part type */
|
||||||
|
|
@ -1623,6 +1631,7 @@ void mmc_destroy(struct mmc *mmc)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef CONFIG_BLK
|
||||||
static int mmc_get_dev(int dev, struct blk_desc **descp)
|
static int mmc_get_dev(int dev, struct blk_desc **descp)
|
||||||
{
|
{
|
||||||
struct mmc *mmc = find_mmc_device(dev);
|
struct mmc *mmc = find_mmc_device(dev);
|
||||||
|
|
@ -1638,6 +1647,7 @@ static int mmc_get_dev(int dev, struct blk_desc **descp)
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/* board-specific MMC power initializations. */
|
/* board-specific MMC power initializations. */
|
||||||
__weak void board_mmc_power_init(void)
|
__weak void board_mmc_power_init(void)
|
||||||
|
|
@ -1729,7 +1739,11 @@ int mmc_init(struct mmc *mmc)
|
||||||
{
|
{
|
||||||
int err = 0;
|
int err = 0;
|
||||||
unsigned start;
|
unsigned start;
|
||||||
|
#ifdef CONFIG_DM_MMC
|
||||||
|
struct mmc_uclass_priv *upriv = dev_get_uclass_priv(mmc->dev);
|
||||||
|
|
||||||
|
upriv->mmc = mmc;
|
||||||
|
#endif
|
||||||
if (mmc->has_init)
|
if (mmc->has_init)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
|
@ -1957,6 +1971,19 @@ int mmc_set_rst_n_function(struct mmc *mmc, u8 enable)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef CONFIG_BLK
|
||||||
|
static const struct blk_ops mmc_blk_ops = {
|
||||||
|
.read = mmc_bread,
|
||||||
|
.write = mmc_bwrite,
|
||||||
|
.select_hwpart = mmc_select_hwpart,
|
||||||
|
};
|
||||||
|
|
||||||
|
U_BOOT_DRIVER(mmc_blk) = {
|
||||||
|
.name = "mmc_blk",
|
||||||
|
.id = UCLASS_BLK,
|
||||||
|
.ops = &mmc_blk_ops,
|
||||||
|
};
|
||||||
|
#else
|
||||||
U_BOOT_LEGACY_BLK(mmc) = {
|
U_BOOT_LEGACY_BLK(mmc) = {
|
||||||
.if_typename = "mmc",
|
.if_typename = "mmc",
|
||||||
.if_type = IF_TYPE_MMC,
|
.if_type = IF_TYPE_MMC,
|
||||||
|
|
@ -1964,3 +1991,4 @@ U_BOOT_LEGACY_BLK(mmc) = {
|
||||||
.get_dev = mmc_get_dev,
|
.get_dev = mmc_get_dev,
|
||||||
.select_hwpart = mmc_select_hwpartp,
|
.select_hwpart = mmc_select_hwpartp,
|
||||||
};
|
};
|
||||||
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -25,8 +25,13 @@ void mmc_adapter_card_type_ident(void);
|
||||||
unsigned long mmc_berase(struct blk_desc *block_dev, lbaint_t start,
|
unsigned long mmc_berase(struct blk_desc *block_dev, lbaint_t start,
|
||||||
lbaint_t blkcnt);
|
lbaint_t blkcnt);
|
||||||
|
|
||||||
unsigned long mmc_bwrite(struct blk_desc *block_dev, lbaint_t start,
|
#ifdef CONFIG_BLK
|
||||||
lbaint_t blkcnt, const void *src);
|
ulong mmc_bwrite(struct udevice *dev, lbaint_t start, lbaint_t blkcnt,
|
||||||
|
const void *src);
|
||||||
|
#else
|
||||||
|
ulong mmc_bwrite(struct blk_desc *block_dev, lbaint_t start, lbaint_t blkcnt,
|
||||||
|
const void *src);
|
||||||
|
#endif
|
||||||
|
|
||||||
#else /* CONFIG_SPL_BUILD */
|
#else /* CONFIG_SPL_BUILD */
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@
|
||||||
|
|
||||||
#include <config.h>
|
#include <config.h>
|
||||||
#include <common.h>
|
#include <common.h>
|
||||||
|
#include <dm.h>
|
||||||
#include <part.h>
|
#include <part.h>
|
||||||
#include <div64.h>
|
#include <div64.h>
|
||||||
#include <linux/math64.h>
|
#include <linux/math64.h>
|
||||||
|
|
@ -172,9 +173,17 @@ static ulong mmc_write_blocks(struct mmc *mmc, lbaint_t start,
|
||||||
return blkcnt;
|
return blkcnt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_BLK
|
||||||
|
ulong mmc_bwrite(struct udevice *dev, lbaint_t start, lbaint_t blkcnt,
|
||||||
|
const void *src)
|
||||||
|
#else
|
||||||
ulong mmc_bwrite(struct blk_desc *block_dev, lbaint_t start, lbaint_t blkcnt,
|
ulong mmc_bwrite(struct blk_desc *block_dev, lbaint_t start, lbaint_t blkcnt,
|
||||||
const void *src)
|
const void *src)
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
|
#ifdef CONFIG_BLK
|
||||||
|
struct blk_desc *block_dev = dev_get_uclass_platdata(dev);
|
||||||
|
#endif
|
||||||
int dev_num = block_dev->devnum;
|
int dev_num = block_dev->devnum;
|
||||||
lbaint_t cur, blocks_todo = blkcnt;
|
lbaint_t cur, blocks_todo = blkcnt;
|
||||||
int err;
|
int err;
|
||||||
|
|
|
||||||
|
|
@ -344,7 +344,9 @@ struct mmc_config {
|
||||||
|
|
||||||
/* TODO struct mmc should be in mmc_private but it's hard to fix right now */
|
/* TODO struct mmc should be in mmc_private but it's hard to fix right now */
|
||||||
struct mmc {
|
struct mmc {
|
||||||
|
#ifndef CONFIG_BLK
|
||||||
struct list_head link;
|
struct list_head link;
|
||||||
|
#endif
|
||||||
const struct mmc_config *cfg; /* provided configuration */
|
const struct mmc_config *cfg; /* provided configuration */
|
||||||
uint version;
|
uint version;
|
||||||
void *priv;
|
void *priv;
|
||||||
|
|
@ -376,7 +378,9 @@ struct mmc {
|
||||||
u64 capacity_gp[4];
|
u64 capacity_gp[4];
|
||||||
u64 enh_user_start;
|
u64 enh_user_start;
|
||||||
u64 enh_user_size;
|
u64 enh_user_size;
|
||||||
|
#ifndef CONFIG_BLK
|
||||||
struct blk_desc block_dev;
|
struct blk_desc block_dev;
|
||||||
|
#endif
|
||||||
char op_cond_pending; /* 1 if we are waiting on an op_cond command */
|
char op_cond_pending; /* 1 if we are waiting on an op_cond command */
|
||||||
char init_in_progress; /* 1 if we have done mmc_start_init() */
|
char init_in_progress; /* 1 if we have done mmc_start_init() */
|
||||||
char preinit; /* start init as early as possible */
|
char preinit; /* start init as early as possible */
|
||||||
|
|
|
||||||
|
|
@ -73,23 +73,6 @@ typedef struct disk_partition {
|
||||||
*/
|
*/
|
||||||
struct blk_desc *blk_get_dev(const char *ifname, int dev);
|
struct blk_desc *blk_get_dev(const char *ifname, int dev);
|
||||||
|
|
||||||
/**
|
|
||||||
* mmc_select_hwpart() - Select the MMC hardware partiion on an MMC device
|
|
||||||
*
|
|
||||||
* MMC devices can support partitioning at the hardware level. This is quite
|
|
||||||
* separate from the normal idea of software-based partitions. MMC hardware
|
|
||||||
* partitions must be explicitly selected. Once selected only the region of
|
|
||||||
* the device covered by that partition is accessible.
|
|
||||||
*
|
|
||||||
* The MMC standard provides for two boot partitions (numbered 1 and 2),
|
|
||||||
* rpmb (3), and up to 4 addition general-purpose partitions (4-7).
|
|
||||||
*
|
|
||||||
* @dev_num: Block device number (struct blk_desc->dev value)
|
|
||||||
* @hwpart: Hardware partition number to select. 0 means the raw device,
|
|
||||||
* 1 is the first partition, 2 is the second, etc.
|
|
||||||
* @return 0 if OK, other value for an error
|
|
||||||
*/
|
|
||||||
int mmc_select_hwpart(int dev_num, int hwpart);
|
|
||||||
struct blk_desc *mg_disk_get_dev(int dev);
|
struct blk_desc *mg_disk_get_dev(int dev);
|
||||||
int host_get_dev_err(int dev, struct blk_desc **blk_devp);
|
int host_get_dev_err(int dev, struct blk_desc **blk_devp);
|
||||||
|
|
||||||
|
|
@ -167,7 +150,6 @@ extern const struct block_drvr block_drvr[];
|
||||||
#else
|
#else
|
||||||
static inline struct blk_desc *blk_get_dev(const char *ifname, int dev)
|
static inline struct blk_desc *blk_get_dev(const char *ifname, int dev)
|
||||||
{ return NULL; }
|
{ return NULL; }
|
||||||
static inline int mmc_select_hwpart(int dev_num, int hwpart) { return -1; }
|
|
||||||
static inline struct blk_desc *mg_disk_get_dev(int dev) { return NULL; }
|
static inline struct blk_desc *mg_disk_get_dev(int dev) { return NULL; }
|
||||||
|
|
||||||
static inline int part_get_info(struct blk_desc *dev_desc, int part,
|
static inline int part_get_info(struct blk_desc *dev_desc, int part,
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue