[U-Boot] [PATCH 2/5] mmc: arm_pl180_mmci: adapt driver to DM usage

Patrice CHOTARD patrice.chotard at st.com
Mon Oct 23 08:08:56 UTC 2017


Hi Jaehoon

On 10/20/2017 03:44 PM, Jaehoon Chung wrote:
> On 10/19/2017 11:45 PM, patrice.chotard at st.com wrote:
>> From: Patrice Chotard <patrice.chotard at st.com>
>>
>> Convert this driver to driver model.
>> This driver is also used by VEXPRESS platforms which doesn't
>> use driver model.
>>
>> Tested on STM32F746 and STM32F769 platforms.
>>
>> Signed-off-by: Christophe Priouzeau <christophe.priouzeau at st.com>
>> Signed-off-by: Patrice Chotard <patrice.chotard at st.com>
>> ---
>>   drivers/mmc/Kconfig          |   9 ++++
>>   drivers/mmc/arm_pl180_mmci.c | 125 ++++++++++++++++++++++++++++++++++++++-----
>>   drivers/mmc/arm_pl180_mmci.h |   3 ++
>>   3 files changed, 125 insertions(+), 12 deletions(-)
>>
>> diff --git a/drivers/mmc/Kconfig b/drivers/mmc/Kconfig
>> index 94050836..62ce0af 100644
>> --- a/drivers/mmc/Kconfig
>> +++ b/drivers/mmc/Kconfig
>> @@ -33,6 +33,15 @@ config SPL_DM_MMC
>>   
>>   if MMC
>>   
>> +config ARM_PL180_MMCI
>> +	bool "ARM AMBA Multimedia Card Interface and compatible support"
>> +	depends on DM_MMC && OF_CONTROL
>> +	help
>> +	  This selects the ARM(R) AMBA(R) PrimeCell Multimedia Card
>> +	  Interface (PL180, PL181 and compatible) support.
>> +	  If you have an ARM(R) platform with a Multimedia Card slot,
>> +	  say Y or M here.
>> +
>>   config SPL_MMC_TINY
>>   	bool "Tiny MMC framework in SPL"
>>   	help
>> diff --git a/drivers/mmc/arm_pl180_mmci.c b/drivers/mmc/arm_pl180_mmci.c
>> index 7898b0d..61dbbfb 100644
>> --- a/drivers/mmc/arm_pl180_mmci.c
>> +++ b/drivers/mmc/arm_pl180_mmci.c
>> @@ -12,12 +12,24 @@
>>   
>>   /* #define DEBUG */
>>   
>> -#include <asm/io.h>
>>   #include "common.h"
>>   #include <errno.h>
>> +#include <malloc.h>
>>   #include <mmc.h>
>> +
>>   #include "arm_pl180_mmci.h"
>> -#include <malloc.h>
>> +
>> +#include <asm/io.h>
>> +
>> +#ifdef CONFIG_DM_MMC
>> +#include <dm.h>
>> +DECLARE_GLOBAL_DATA_PTR;
>> +
>> +struct arm_pl180_mmc_plat {
>> +	struct mmc_config cfg;
>> +	struct mmc mmc;
>> +};
>> +#endif
>>   
>>   static int wait_for_command_end(struct mmc *dev, struct mmc_cmd *cmd)
>>   {
>> @@ -265,16 +277,6 @@ static int host_request(struct mmc *dev,
>>   	return result;
>>   }
>>   
>> -/* MMC uses open drain drivers in the enumeration phase */
>> -static int mmc_host_reset(struct mmc *dev)
>> -{
>> -	struct pl180_mmc_host *host = dev->priv;
>> -
>> -	writel(host->pwr_init, &host->base->power);
>> -
>> -	return 0;
>> -}
>> -
>>   static int  host_set_ios(struct mmc *dev)
>>   {
>>   	struct pl180_mmc_host *host = dev->priv;
>> @@ -337,11 +339,23 @@ static int  host_set_ios(struct mmc *dev)
>>   	return 0;
>>   }
>>   
>> +#ifndef CONFIG_DM_MMC
>> +/* MMC uses open drain drivers in the enumeration phase */
>> +static int mmc_host_reset(struct mmc *dev)
>> +{
>> +	struct pl180_mmc_host *host = dev->priv;
>> +
>> +	writel(host->pwr_init, &host->base->power);
>> +
>> +	return 0;
>> +}
>> +
>>   static const struct mmc_ops arm_pl180_mmci_ops = {
>>   	.send_cmd = host_request,
>>   	.set_ios = host_set_ios,
>>   	.init = mmc_host_reset,
>>   };
>> +#endif
>>   
>>   /*
>>    * mmc_host_init - initialize the mmc controller.
>> @@ -361,7 +375,9 @@ int arm_pl180_mmci_init(struct pl180_mmc_host *host, struct mmc **mmc)
>>   	writel(sdi_u32, &host->base->mask0);
>>   
>>   	host->cfg.name = host->name;
>> +#ifndef CONFIG_DM_MMC
>>   	host->cfg.ops = &arm_pl180_mmci_ops;
>> +#endif
>>   	/* TODO remove the duplicates */
>>   	host->cfg.host_caps = host->caps;
>>   	host->cfg.voltages = host->voltages;
>> @@ -381,3 +397,88 @@ int arm_pl180_mmci_init(struct pl180_mmc_host *host, struct mmc **mmc)
>>   
>>   	return 0;
>>   }
>> +
>> +#ifdef CONFIG_DM_MMC
>> +static int arm_pl180_mmc_probe(struct udevice *dev)
>> +{
>> +	struct arm_pl180_mmc_plat *pdata = dev_get_platdata(dev);
>> +	struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev);
>> +	struct mmc *mmc = &pdata->mmc;
>> +	struct pl180_mmc_host *host = mmc->priv;
>> +	int ret;
>> +
>> +	strcpy(host->name, "MMC");
>> +	host->pwr_init = INIT_PWR;
>> +	host->clkdiv_init = SDI_CLKCR_CLKDIV_INIT_V1 | SDI_CLKCR_CLKEN |
>> +			    SDI_CLKCR_HWFC_EN;
>> +	host->voltages = VOLTAGE_WINDOW_SD;
>> +	host->caps = 0;
>> +	host->clock_in = 48000000;
> 
> Use the defined variable instead of 480000000.

OK

> 
>> +	host->clock_min = 400000;
> 
> Ditto.

OK

> 
>> +	host->clock_max = dev_read_u32_default(dev, "max-frequency", 48000000);
>> +	host->version2 = dev_get_driver_data(dev);
>> +	ret = arm_pl180_mmci_init(host, &mmc);
>> +	if (ret) {
>> +		dev_err(dev, "arm_pl180_mmci init failed\n");
>> +		return ret;
>> +	}
>> +
>> +	mmc->dev = dev;
>> +	dev->priv = host;
>> +	upriv->mmc = mmc;
>> +
>> +	return 0;
>> +}
>> +
>> +static int dm_host_request(struct udevice *dev, struct mmc_cmd *cmd,
>> +			   struct mmc_data *data)
>> +{
>> +	struct mmc *mmc = mmc_get_mmc_dev(dev);
>> +
>> +	return host_request(mmc, cmd, data);
>> +}
>> +
>> +static int dm_host_set_ios(struct udevice *dev)
>> +{
>> +	struct mmc *mmc = mmc_get_mmc_dev(dev);
>> +
>> +	return host_set_ios(mmc);
>> +}
>> +
>> +static const struct dm_mmc_ops arm_pl180_dm_mmc_ops = {
>> +	.send_cmd = dm_host_request,
>> +	.set_ios = dm_host_set_ios,
>> +};
>> +
>> +static int arm_pl180_mmc_ofdata_to_platdata(struct udevice *dev)
>> +{
>> +	struct arm_pl180_mmc_plat *pdata = dev_get_platdata(dev);
>> +	struct mmc *mmc = &pdata->mmc;
>> +	struct pl180_mmc_host *host = mmc->priv;
>> +	fdt_addr_t addr;
>> +
>> +	addr = devfdt_get_addr(dev);
>> +	if (addr == FDT_ADDR_T_NONE)
>> +		return -EINVAL;
>> +
>> +	host->base = (void *)addr;
>> +
>> +	return 0;
>> +}
>> +
>> +static const struct udevice_id arm_pl180_mmc_match[] = {
>> +	{ .compatible = "st,stm32f4xx-sdio", .data = VERSION1 },
>> +	{ /* sentinel */ }
>> +};
>> +
>> +U_BOOT_DRIVER(arm_pl180_mmc) = {
>> +	.name = "arm_pl180_mmc",
>> +	.id = UCLASS_MMC,
>> +	.of_match = arm_pl180_mmc_match,
>> +	.ops = &arm_pl180_dm_mmc_ops,
>> +	.probe = arm_pl180_mmc_probe,
>> +	.ofdata_to_platdata = arm_pl180_mmc_ofdata_to_platdata,
>> +	.priv_auto_alloc_size = sizeof(struct pl180_mmc_host),
>> +	.platdata_auto_alloc_size = sizeof(struct arm_pl180_mmc_plat),
>> +};
>> +#endif
>> diff --git a/drivers/mmc/arm_pl180_mmci.h b/drivers/mmc/arm_pl180_mmci.h
>> index 6e232f7..b935288 100644
>> --- a/drivers/mmc/arm_pl180_mmci.h
>> +++ b/drivers/mmc/arm_pl180_mmci.h
>> @@ -142,6 +142,9 @@
>>   
>>   #define SDI_FIFO_BURST_SIZE	8
>>   
>> +#define VERSION1	false
>> +#define VERSION2	true
> 
> Where do this use?

This defines are used to indicated which IP version is supported.
In do_data_transfer(), depending on host->version2 value, blksz bits are 
not located at the same location inside data_ctrl registers.

Patrice

> 
>> +
>>   struct sdi_registers {
>>   	u32 power;		/* 0x00*/
>>   	u32 clock;		/* 0x04*/
>>
> 


More information about the U-Boot mailing list