dm: mmc: Add a way to use driver model for MMC operations
The driver model conversion for MMC has moved in small steps. The first step was to have an MMC device (CONFIG_DM_MMC). The second was to use a child block device (CONFIG_BLK). The final one is to use driver model for MMC operations (CONFIG_DM_MMC_OP). Add support for this. The immediate priority is to make all boards that use DM_MMC also use those other two options. This will allow them to be removed. Signed-off-by: Simon Glass <sjg@chromium.org>
This commit is contained in:
		
							parent
							
								
									7d1c8d99fd
								
							
						
					
					
						commit
						8ca51e51c1
					
				|  | @ -16,6 +16,15 @@ config DM_MMC | ||||||
| 	  appear as block devices in U-Boot and can support filesystems such | 	  appear as block devices in U-Boot and can support filesystems such | ||||||
| 	  as EXT4 and FAT. | 	  as EXT4 and FAT. | ||||||
| 
 | 
 | ||||||
|  | config DM_MMC_OPS | ||||||
|  | 	bool "Support MMC controller operations using Driver Model" | ||||||
|  | 	depends on DM_MMC | ||||||
|  | 	help | ||||||
|  | 	  Driver model provides a means of supporting device operations. This | ||||||
|  | 	  option moves MMC operations under the control of driver model. The | ||||||
|  | 	  option will be removed as soon as all DM_MMC drivers use it, as it | ||||||
|  | 	  will the only supported behaviour. | ||||||
|  | 
 | ||||||
| config MSM_SDHCI | config MSM_SDHCI | ||||||
| 	bool "Qualcomm SDHCI controller" | 	bool "Qualcomm SDHCI controller" | ||||||
| 	depends on DM_MMC | 	depends on DM_MMC | ||||||
|  |  | ||||||
|  | @ -13,6 +13,72 @@ | ||||||
| #include <dm/root.h> | #include <dm/root.h> | ||||||
| #include "mmc_private.h" | #include "mmc_private.h" | ||||||
| 
 | 
 | ||||||
|  | #ifdef CONFIG_DM_MMC_OPS | ||||||
|  | int dm_mmc_send_cmd(struct udevice *dev, struct mmc_cmd *cmd, | ||||||
|  | 		    struct mmc_data *data) | ||||||
|  | { | ||||||
|  | 	struct mmc *mmc = mmc_get_mmc_dev(dev); | ||||||
|  | 	struct dm_mmc_ops *ops = mmc_get_ops(dev); | ||||||
|  | 	int ret; | ||||||
|  | 
 | ||||||
|  | 	mmmc_trace_before_send(mmc, cmd); | ||||||
|  | 	if (ops->send_cmd) | ||||||
|  | 		ret = ops->send_cmd(dev, cmd, data); | ||||||
|  | 	else | ||||||
|  | 		ret = -ENOSYS; | ||||||
|  | 	mmmc_trace_after_send(mmc, cmd, ret); | ||||||
|  | 
 | ||||||
|  | 	return ret; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data) | ||||||
|  | { | ||||||
|  | 	return dm_mmc_send_cmd(mmc->dev, cmd, data); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | int dm_mmc_set_ios(struct udevice *dev) | ||||||
|  | { | ||||||
|  | 	struct dm_mmc_ops *ops = mmc_get_ops(dev); | ||||||
|  | 
 | ||||||
|  | 	if (!ops->set_ios) | ||||||
|  | 		return -ENOSYS; | ||||||
|  | 	return ops->set_ios(dev); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | int mmc_set_ios(struct mmc *mmc) | ||||||
|  | { | ||||||
|  | 	return dm_mmc_set_ios(mmc->dev); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | int dm_mmc_get_wp(struct udevice *dev) | ||||||
|  | { | ||||||
|  | 	struct dm_mmc_ops *ops = mmc_get_ops(dev); | ||||||
|  | 
 | ||||||
|  | 	if (!ops->get_wp) | ||||||
|  | 		return -ENOSYS; | ||||||
|  | 	return ops->get_wp(dev); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | int mmc_getwp(struct mmc *mmc) | ||||||
|  | { | ||||||
|  | 	return dm_mmc_get_wp(mmc->dev); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | int dm_mmc_get_cd(struct udevice *dev) | ||||||
|  | { | ||||||
|  | 	struct dm_mmc_ops *ops = mmc_get_ops(dev); | ||||||
|  | 
 | ||||||
|  | 	if (!ops->get_cd) | ||||||
|  | 		return -ENOSYS; | ||||||
|  | 	return ops->get_cd(dev); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | int mmc_getcd(struct mmc *mmc) | ||||||
|  | { | ||||||
|  | 	return dm_mmc_get_cd(mmc->dev); | ||||||
|  | } | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
| struct mmc *mmc_get_mmc_dev(struct udevice *dev) | struct mmc *mmc_get_mmc_dev(struct udevice *dev) | ||||||
| { | { | ||||||
| 	struct mmc_uclass_priv *upriv; | 	struct mmc_uclass_priv *upriv; | ||||||
|  |  | ||||||
|  | @ -21,6 +21,7 @@ | ||||||
| #include <div64.h> | #include <div64.h> | ||||||
| #include "mmc_private.h" | #include "mmc_private.h" | ||||||
| 
 | 
 | ||||||
|  | #ifndef CONFIG_DM_MMC_OPS | ||||||
| __weak int board_mmc_getwp(struct mmc *mmc) | __weak int board_mmc_getwp(struct mmc *mmc) | ||||||
| { | { | ||||||
| 	return -1; | 	return -1; | ||||||
|  | @ -46,6 +47,7 @@ __weak int board_mmc_getcd(struct mmc *mmc) | ||||||
| { | { | ||||||
| 	return -1; | 	return -1; | ||||||
| } | } | ||||||
|  | #endif | ||||||
| 
 | 
 | ||||||
| #ifdef CONFIG_MMC_TRACE | #ifdef CONFIG_MMC_TRACE | ||||||
| void mmmc_trace_before_send(struct mmc *mmc, struct mmc_cmd *cmd) | void mmmc_trace_before_send(struct mmc *mmc, struct mmc_cmd *cmd) | ||||||
|  | @ -115,6 +117,7 @@ void mmc_trace_state(struct mmc *mmc, struct mmc_cmd *cmd) | ||||||
| } | } | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
|  | #ifndef CONFIG_DM_MMC_OPS | ||||||
| int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data) | int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data) | ||||||
| { | { | ||||||
| 	int ret; | 	int ret; | ||||||
|  | @ -125,6 +128,7 @@ int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data) | ||||||
| 
 | 
 | ||||||
| 	return ret; | 	return ret; | ||||||
| } | } | ||||||
|  | #endif | ||||||
| 
 | 
 | ||||||
| int mmc_send_status(struct mmc *mmc, int timeout) | int mmc_send_status(struct mmc *mmc, int timeout) | ||||||
| { | { | ||||||
|  | @ -789,6 +793,7 @@ int mmc_hwpart_config(struct mmc *mmc, | ||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | #ifndef CONFIG_DM_MMC_OPS | ||||||
| int mmc_getcd(struct mmc *mmc) | int mmc_getcd(struct mmc *mmc) | ||||||
| { | { | ||||||
| 	int cd; | 	int cd; | ||||||
|  | @ -804,6 +809,7 @@ int mmc_getcd(struct mmc *mmc) | ||||||
| 
 | 
 | ||||||
| 	return cd; | 	return cd; | ||||||
| } | } | ||||||
|  | #endif | ||||||
| 
 | 
 | ||||||
| static int sd_switch(struct mmc *mmc, int mode, int group, u8 value, u8 *resp) | static int sd_switch(struct mmc *mmc, int mode, int group, u8 value, u8 *resp) | ||||||
| { | { | ||||||
|  | @ -967,11 +973,13 @@ static const u8 multipliers[] = { | ||||||
| 	80, | 	80, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  | #ifndef CONFIG_DM_MMC_OPS | ||||||
| static void mmc_set_ios(struct mmc *mmc) | static void mmc_set_ios(struct mmc *mmc) | ||||||
| { | { | ||||||
| 	if (mmc->cfg->ops->set_ios) | 	if (mmc->cfg->ops->set_ios) | ||||||
| 		mmc->cfg->ops->set_ios(mmc); | 		mmc->cfg->ops->set_ios(mmc); | ||||||
| } | } | ||||||
|  | #endif | ||||||
| 
 | 
 | ||||||
| void mmc_set_clock(struct mmc *mmc, uint clock) | void mmc_set_clock(struct mmc *mmc, uint clock) | ||||||
| { | { | ||||||
|  | @ -1505,10 +1513,15 @@ __weak void board_mmc_power_init(void) | ||||||
| 
 | 
 | ||||||
| int mmc_start_init(struct mmc *mmc) | int mmc_start_init(struct mmc *mmc) | ||||||
| { | { | ||||||
|  | 	bool no_card; | ||||||
| 	int err; | 	int err; | ||||||
| 
 | 
 | ||||||
| 	/* we pretend there's no card when init is NULL */ | 	/* we pretend there's no card when init is NULL */ | ||||||
| 	if (mmc_getcd(mmc) == 0 || mmc->cfg->ops->init == NULL) { | 	no_card = mmc_getcd(mmc) == 0; | ||||||
|  | #ifndef CONFIG_DM_MMC_OPS | ||||||
|  | 	no_card = no_card || (mmc->cfg->ops->init == NULL); | ||||||
|  | #endif | ||||||
|  | 	if (no_card) { | ||||||
| 		mmc->has_init = 0; | 		mmc->has_init = 0; | ||||||
| #if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT) | #if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT) | ||||||
| 		printf("MMC: no card present\n"); | 		printf("MMC: no card present\n"); | ||||||
|  | @ -1524,12 +1537,14 @@ int mmc_start_init(struct mmc *mmc) | ||||||
| #endif | #endif | ||||||
| 	board_mmc_power_init(); | 	board_mmc_power_init(); | ||||||
| 
 | 
 | ||||||
|  | #ifdef CONFIG_DM_MMC_OPS | ||||||
|  | 	/* The device has already been probed ready for use */ | ||||||
|  | #else | ||||||
| 	/* made sure it's not NULL earlier */ | 	/* made sure it's not NULL earlier */ | ||||||
| 	err = mmc->cfg->ops->init(mmc); | 	err = mmc->cfg->ops->init(mmc); | ||||||
| 
 |  | ||||||
| 	if (err) | 	if (err) | ||||||
| 		return err; | 		return err; | ||||||
| 
 | #endif | ||||||
| 	mmc->ddr_mode = 0; | 	mmc->ddr_mode = 0; | ||||||
| 	mmc_set_bus_width(mmc, 1); | 	mmc_set_bus_width(mmc, 1); | ||||||
| 	mmc_set_clock(mmc, 1); | 	mmc_set_clock(mmc, 1); | ||||||
|  |  | ||||||
|  | @ -323,6 +323,58 @@ struct mmc_data { | ||||||
| /* forward decl. */ | /* forward decl. */ | ||||||
| struct mmc; | struct mmc; | ||||||
| 
 | 
 | ||||||
|  | #ifdef CONFIG_DM_MMC_OPS | ||||||
|  | struct dm_mmc_ops { | ||||||
|  | 	/**
 | ||||||
|  | 	 * send_cmd() - Send a command to the MMC device | ||||||
|  | 	 * | ||||||
|  | 	 * @dev:	Device to receive the command | ||||||
|  | 	 * @cmd:	Command to send | ||||||
|  | 	 * @data:	Additional data to send/receive | ||||||
|  | 	 * @return 0 if OK, -ve on error | ||||||
|  | 	 */ | ||||||
|  | 	int (*send_cmd)(struct udevice *dev, struct mmc_cmd *cmd, | ||||||
|  | 			struct mmc_data *data); | ||||||
|  | 
 | ||||||
|  | 	/**
 | ||||||
|  | 	 * set_ios() - Set the I/O speed/width for an MMC device | ||||||
|  | 	 * | ||||||
|  | 	 * @dev:	Device to update | ||||||
|  | 	 * @return 0 if OK, -ve on error | ||||||
|  | 	 */ | ||||||
|  | 	int (*set_ios)(struct udevice *dev); | ||||||
|  | 
 | ||||||
|  | 	/**
 | ||||||
|  | 	 * get_cd() - See whether a card is present | ||||||
|  | 	 * | ||||||
|  | 	 * @dev:	Device to check | ||||||
|  | 	 * @return 0 if not present, 1 if present, -ve on error | ||||||
|  | 	 */ | ||||||
|  | 	int (*get_cd)(struct udevice *dev); | ||||||
|  | 
 | ||||||
|  | 	/**
 | ||||||
|  | 	 * get_wp() - See whether a card has write-protect enabled | ||||||
|  | 	 * | ||||||
|  | 	 * @dev:	Device to check | ||||||
|  | 	 * @return 0 if write-enabled, 1 if write-protected, -ve on error | ||||||
|  | 	 */ | ||||||
|  | 	int (*get_wp)(struct udevice *dev); | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | #define mmc_get_ops(dev)        ((struct dm_mmc_ops *)(dev)->driver->ops) | ||||||
|  | 
 | ||||||
|  | int dm_mmc_send_cmd(struct udevice *dev, struct mmc_cmd *cmd, | ||||||
|  | 		    struct mmc_data *data); | ||||||
|  | int dm_mmc_set_ios(struct udevice *dev); | ||||||
|  | int dm_mmc_get_cd(struct udevice *dev); | ||||||
|  | int dm_mmc_get_wp(struct udevice *dev); | ||||||
|  | 
 | ||||||
|  | /* Transition functions for compatibility */ | ||||||
|  | int mmc_set_ios(struct mmc *mmc); | ||||||
|  | int mmc_getcd(struct mmc *mmc); | ||||||
|  | int mmc_getwp(struct mmc *mmc); | ||||||
|  | 
 | ||||||
|  | #else | ||||||
| struct mmc_ops { | struct mmc_ops { | ||||||
| 	int (*send_cmd)(struct mmc *mmc, | 	int (*send_cmd)(struct mmc *mmc, | ||||||
| 			struct mmc_cmd *cmd, struct mmc_data *data); | 			struct mmc_cmd *cmd, struct mmc_data *data); | ||||||
|  | @ -331,10 +383,13 @@ struct mmc_ops { | ||||||
| 	int (*getcd)(struct mmc *mmc); | 	int (*getcd)(struct mmc *mmc); | ||||||
| 	int (*getwp)(struct mmc *mmc); | 	int (*getwp)(struct mmc *mmc); | ||||||
| }; | }; | ||||||
|  | #endif | ||||||
| 
 | 
 | ||||||
| struct mmc_config { | struct mmc_config { | ||||||
| 	const char *name; | 	const char *name; | ||||||
|  | #ifndef CONFIG_DM_MMC_OPS | ||||||
| 	const struct mmc_ops *ops; | 	const struct mmc_ops *ops; | ||||||
|  | #endif | ||||||
| 	uint host_caps; | 	uint host_caps; | ||||||
| 	uint voltages; | 	uint voltages; | ||||||
| 	uint f_min; | 	uint f_min; | ||||||
|  | @ -343,7 +398,12 @@ struct mmc_config { | ||||||
| 	unsigned char part_type; | 	unsigned char part_type; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| /* TODO struct mmc should be in mmc_private but it's hard to fix right now */ | /*
 | ||||||
|  |  * With CONFIG_DM_MMC enabled, struct mmc can be accessed from the MMC device | ||||||
|  |  * with mmc_get_mmc_dev(). | ||||||
|  |  * | ||||||
|  |  * TODO struct mmc should be in mmc_private but it's hard to fix right now | ||||||
|  |  */ | ||||||
| struct mmc { | struct mmc { | ||||||
| #ifndef CONFIG_BLK | #ifndef CONFIG_BLK | ||||||
| 	struct list_head link; | 	struct list_head link; | ||||||
|  | @ -446,10 +506,14 @@ void print_mmc_devices(char separator); | ||||||
| int get_mmc_num(void); | int get_mmc_num(void); | ||||||
| int mmc_hwpart_config(struct mmc *mmc, const struct mmc_hwpart_conf *conf, | int mmc_hwpart_config(struct mmc *mmc, const struct mmc_hwpart_conf *conf, | ||||||
| 		      enum mmc_hwpart_conf_mode mode); | 		      enum mmc_hwpart_conf_mode mode); | ||||||
|  | 
 | ||||||
|  | #ifndef CONFIG_DM_MMC_OPS | ||||||
| int mmc_getcd(struct mmc *mmc); | int mmc_getcd(struct mmc *mmc); | ||||||
| int board_mmc_getcd(struct mmc *mmc); | int board_mmc_getcd(struct mmc *mmc); | ||||||
| int mmc_getwp(struct mmc *mmc); | int mmc_getwp(struct mmc *mmc); | ||||||
| int board_mmc_getwp(struct mmc *mmc); | int board_mmc_getwp(struct mmc *mmc); | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
| int mmc_set_dsr(struct mmc *mmc, u16 val); | int mmc_set_dsr(struct mmc *mmc, u16 val); | ||||||
| /* Function to change the size of boot partition and rpmb partitions */ | /* Function to change the size of boot partition and rpmb partitions */ | ||||||
| int mmc_boot_partition_size_change(struct mmc *mmc, unsigned long bootsize, | int mmc_boot_partition_size_change(struct mmc *mmc, unsigned long bootsize, | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue