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 | ||||
| 	  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 | ||||
| 	bool "Qualcomm SDHCI controller" | ||||
| 	depends on DM_MMC | ||||
|  |  | |||
|  | @ -13,6 +13,72 @@ | |||
| #include <dm/root.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_uclass_priv *upriv; | ||||
|  |  | |||
|  | @ -21,6 +21,7 @@ | |||
| #include <div64.h> | ||||
| #include "mmc_private.h" | ||||
| 
 | ||||
| #ifndef CONFIG_DM_MMC_OPS | ||||
| __weak int board_mmc_getwp(struct mmc *mmc) | ||||
| { | ||||
| 	return -1; | ||||
|  | @ -46,6 +47,7 @@ __weak int board_mmc_getcd(struct mmc *mmc) | |||
| { | ||||
| 	return -1; | ||||
| } | ||||
| #endif | ||||
| 
 | ||||
| #ifdef CONFIG_MMC_TRACE | ||||
| 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 | ||||
| 
 | ||||
| #ifndef CONFIG_DM_MMC_OPS | ||||
| int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data) | ||||
| { | ||||
| 	int ret; | ||||
|  | @ -125,6 +128,7 @@ int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data) | |||
| 
 | ||||
| 	return ret; | ||||
| } | ||||
| #endif | ||||
| 
 | ||||
| int mmc_send_status(struct mmc *mmc, int timeout) | ||||
| { | ||||
|  | @ -789,6 +793,7 @@ int mmc_hwpart_config(struct mmc *mmc, | |||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| #ifndef CONFIG_DM_MMC_OPS | ||||
| int mmc_getcd(struct mmc *mmc) | ||||
| { | ||||
| 	int cd; | ||||
|  | @ -804,6 +809,7 @@ int mmc_getcd(struct mmc *mmc) | |||
| 
 | ||||
| 	return cd; | ||||
| } | ||||
| #endif | ||||
| 
 | ||||
| static int sd_switch(struct mmc *mmc, int mode, int group, u8 value, u8 *resp) | ||||
| { | ||||
|  | @ -967,11 +973,13 @@ static const u8 multipliers[] = { | |||
| 	80, | ||||
| }; | ||||
| 
 | ||||
| #ifndef CONFIG_DM_MMC_OPS | ||||
| static void mmc_set_ios(struct mmc *mmc) | ||||
| { | ||||
| 	if (mmc->cfg->ops->set_ios) | ||||
| 		mmc->cfg->ops->set_ios(mmc); | ||||
| } | ||||
| #endif | ||||
| 
 | ||||
| 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) | ||||
| { | ||||
| 	bool no_card; | ||||
| 	int err; | ||||
| 
 | ||||
| 	/* 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; | ||||
| #if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT) | ||||
| 		printf("MMC: no card present\n"); | ||||
|  | @ -1524,12 +1537,14 @@ int mmc_start_init(struct mmc *mmc) | |||
| #endif | ||||
| 	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 */ | ||||
| 	err = mmc->cfg->ops->init(mmc); | ||||
| 
 | ||||
| 	if (err) | ||||
| 		return err; | ||||
| 
 | ||||
| #endif | ||||
| 	mmc->ddr_mode = 0; | ||||
| 	mmc_set_bus_width(mmc, 1); | ||||
| 	mmc_set_clock(mmc, 1); | ||||
|  |  | |||
|  | @ -323,6 +323,58 @@ struct mmc_data { | |||
| /* forward decl. */ | ||||
| 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 { | ||||
| 	int (*send_cmd)(struct mmc *mmc, | ||||
| 			struct mmc_cmd *cmd, struct mmc_data *data); | ||||
|  | @ -331,10 +383,13 @@ struct mmc_ops { | |||
| 	int (*getcd)(struct mmc *mmc); | ||||
| 	int (*getwp)(struct mmc *mmc); | ||||
| }; | ||||
| #endif | ||||
| 
 | ||||
| struct mmc_config { | ||||
| 	const char *name; | ||||
| #ifndef CONFIG_DM_MMC_OPS | ||||
| 	const struct mmc_ops *ops; | ||||
| #endif | ||||
| 	uint host_caps; | ||||
| 	uint voltages; | ||||
| 	uint f_min; | ||||
|  | @ -343,7 +398,12 @@ struct mmc_config { | |||
| 	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 { | ||||
| #ifndef CONFIG_BLK | ||||
| 	struct list_head link; | ||||
|  | @ -446,10 +506,14 @@ void print_mmc_devices(char separator); | |||
| int get_mmc_num(void); | ||||
| int mmc_hwpart_config(struct mmc *mmc, const struct mmc_hwpart_conf *conf, | ||||
| 		      enum mmc_hwpart_conf_mode mode); | ||||
| 
 | ||||
| #ifndef CONFIG_DM_MMC_OPS | ||||
| int mmc_getcd(struct mmc *mmc); | ||||
| int board_mmc_getcd(struct mmc *mmc); | ||||
| int mmc_getwp(struct mmc *mmc); | ||||
| int board_mmc_getwp(struct mmc *mmc); | ||||
| #endif | ||||
| 
 | ||||
| int mmc_set_dsr(struct mmc *mmc, u16 val); | ||||
| /* Function to change the size of boot partition and rpmb partitions */ | ||||
| int mmc_boot_partition_size_change(struct mmc *mmc, unsigned long bootsize, | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue