[U-Boot] [PATCH v5] mmc: gen_atmel_mci: add driver model support for mci

Yang, Wenyou Wenyou.Yang at Microchip.com
Wed Apr 5 00:25:30 UTC 2017


Hi Jaehoon,


On 2017/3/30 12:30, Jaehoon Chung wrote:
> Hi Wenyou,
>
> On 03/23/2017 01:48 PM, Wenyou Yang wrote:
>> Add the driver model support for Atmel mci while retaining the
>> existing legacy code. This allows the driver to support boards
>> that have converted to driver model as well as those that have not.
>>
>> Signed-off-by: Wenyou Yang <wenyou.yang at atmel.com>
> If Andreas is ok, i will pick this. Otherwise, pick this with my ack.
> Let me know, plz.

Andreas, are you okay?

>
> Acked-by: Jaehoon Chung <jh80.chung at samsung.com>
>
> Best Regards,
> Jaehoon Chung
>
>> ---
>>
>> Changes in v5:
>>   - Rebase on v2017.03.
>>
>> Changes in v4:
>>   - Remove unneeded #ifdef CONFIG_DM_MMC.
>>
>> Changes in v3:
>>   - Use unified #ifdef CONFIG_DM_MMC #else...#endif, instead of #ifndef CONFIG_DM_MMC
>>     #else...#endif.
>>
>> Changes in v2:
>>   - Change the return type of atmel_mci_setup_cfg() from int to void.
>>   - Add comments on the features depends on the IP version.
>>   - Add the error handle path of clock.
>>   - Fix the missing use priv->bus_clk_rate.
>>   - Return from mmc_bind() directly, instead of checking its return.
>>
>>   drivers/mmc/Kconfig         |   9 +++
>>   drivers/mmc/gen_atmel_mci.c | 158 +++++++++++++++++++++++++++++++++++++++++++-
>>   2 files changed, 166 insertions(+), 1 deletion(-)
>>
>> diff --git a/drivers/mmc/Kconfig b/drivers/mmc/Kconfig
>> index 01d1dbfb1b..cb9937b4eb 100644
>> --- a/drivers/mmc/Kconfig
>> +++ b/drivers/mmc/Kconfig
>> @@ -336,6 +336,15 @@ config MMC_SUNXI
>>   	  This selects support for the SD/MMC Host Controller on
>>   	  Allwinner sunxi SoCs.
>>   
>> +config GENERIC_ATMEL_MCI
>> +	bool "Atmel Multimedia Card Interface support"
>> +	depends on DM_MMC && BLK && DM_MMC_OPS && ARCH_AT91
>> +	help
>> +	  This enables support for Atmel High Speed Multimedia Card Interface
>> +	  (HSMCI), which supports the MultiMedia Card (MMC) Specification V4.3,
>> +	  the SD Memory Card Specification V2.0, the SDIO V2.0 specification
>> +	  and CE-ATA V1.1.
>> +
>>   endif
>>   
>>   endmenu
>> diff --git a/drivers/mmc/gen_atmel_mci.c b/drivers/mmc/gen_atmel_mci.c
>> index 7dc4a5de74..c25d9ed96e 100644
>> --- a/drivers/mmc/gen_atmel_mci.c
>> +++ b/drivers/mmc/gen_atmel_mci.c
>> @@ -10,6 +10,7 @@
>>    */
>>   
>>   #include <common.h>
>> +#include <clk.h>
>>   #include <mmc.h>
>>   #include <part.h>
>>   #include <malloc.h>
>> @@ -18,8 +19,11 @@
>>   #include <asm/byteorder.h>
>>   #include <asm/arch/clk.h>
>>   #include <asm/arch/hardware.h>
>> +#include <dm/device.h>
>>   #include "atmel_mci.h"
>>   
>> +DECLARE_GLOBAL_DATA_PTR;
>> +
>>   #ifndef CONFIG_SYS_MMC_CLK_OD
>>   # define CONFIG_SYS_MMC_CLK_OD	150000
>>   #endif
>> @@ -37,6 +41,10 @@ struct atmel_mci_priv {
>>   	struct atmel_mci	*mci;
>>   	unsigned int		initialized:1;
>>   	unsigned int		curr_clk;
>> +#ifdef CONFIG_DM_MMC
>> +	struct mmc	mmc;
>> +	ulong		bus_clk_rate;
>> +#endif
>>   };
>>   
>>   /* Read Atmel MCI IP version */
>> @@ -58,11 +66,19 @@ static void dump_cmd(u32 cmdr, u32 arg, u32 status, const char* msg)
>>   }
>>   
>>   /* Setup for MCI Clock and Block Size */
>> +#ifdef CONFIG_DM_MMC
>> +static void mci_set_mode(struct atmel_mci_priv *priv, u32 hz, u32 blklen)
>> +{
>> +	struct mmc *mmc = &priv->mmc;
>> +	u32 bus_hz = priv->bus_clk_rate;
>> +#else
>>   static void mci_set_mode(struct mmc *mmc, u32 hz, u32 blklen)
>>   {
>>   	struct atmel_mci_priv *priv = mmc->priv;
>> -	atmel_mci_t *mci = priv->mci;
>>   	u32 bus_hz = get_mci_clk_rate();
>> +#endif
>> +
>> +	atmel_mci_t *mci = priv->mci;
>>   	u32 clkdiv = 255;
>>   	unsigned int version = atmel_mci_get_version(mci);
>>   	u32 clkodd = 0;
>> @@ -202,10 +218,18 @@ io_fail:
>>    * Sends a command out on the bus and deals with the block data.
>>    * Takes the mmc pointer, a command pointer, and an optional data pointer.
>>    */
>> +#ifdef CONFIG_DM_MMC
>> +static int atmel_mci_send_cmd(struct udevice *dev, struct mmc_cmd *cmd,
>> +			      struct mmc_data *data)
>> +{
>> +	struct atmel_mci_priv *priv = dev_get_priv(dev);
>> +	struct mmc *mmc = mmc_get_mmc_dev(dev);
>> +#else
>>   static int
>>   mci_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data)
>>   {
>>   	struct atmel_mci_priv *priv = mmc->priv;
>> +#endif
>>   	atmel_mci_t *mci = priv->mci;
>>   	u32 cmdr;
>>   	u32 error_flags = 0;
>> @@ -335,17 +359,28 @@ mci_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data)
>>   	return 0;
>>   }
>>   
>> +#ifdef CONFIG_DM_MMC
>> +static int atmel_mci_set_ios(struct udevice *dev)
>> +{
>> +	struct atmel_mci_priv *priv = dev_get_priv(dev);
>> +	struct mmc *mmc = mmc_get_mmc_dev(dev);
>> +#else
>>   /* Entered into mmc structure during driver init */
>>   static int mci_set_ios(struct mmc *mmc)
>>   {
>>   	struct atmel_mci_priv *priv = mmc->priv;
>> +#endif
>>   	atmel_mci_t *mci = priv->mci;
>>   	int bus_width = mmc->bus_width;
>>   	unsigned int version = atmel_mci_get_version(mci);
>>   	int busw;
>>   
>>   	/* Set the clock speed */
>> +#ifdef CONFIG_DM_MMC
>> +	mci_set_mode(priv, mmc->clock, MMC_DEFAULT_BLKLEN);
>> +#else
>>   	mci_set_mode(mmc, mmc->clock, MMC_DEFAULT_BLKLEN);
>> +#endif
>>   
>>   	/*
>>   	 * set the bus width and select slot for this interface
>> @@ -374,10 +409,15 @@ static int mci_set_ios(struct mmc *mmc)
>>   	return 0;
>>   }
>>   
>> +#ifdef CONFIG_DM_MMC
>> +static int atmel_mci_hw_init(struct atmel_mci_priv *priv)
>> +{
>> +#else
>>   /* Entered into mmc structure during driver init */
>>   static int mci_init(struct mmc *mmc)
>>   {
>>   	struct atmel_mci_priv *priv = mmc->priv;
>> +#endif
>>   	atmel_mci_t *mci = priv->mci;
>>   
>>   	/* Initialize controller */
>> @@ -392,11 +432,16 @@ static int mci_init(struct mmc *mmc)
>>   	writel(~0UL, &mci->idr);
>>   
>>   	/* Set default clocks and blocklen */
>> +#ifdef CONFIG_DM_MMC
>> +	mci_set_mode(priv, CONFIG_SYS_MMC_CLK_OD, MMC_DEFAULT_BLKLEN);
>> +#else
>>   	mci_set_mode(mmc, CONFIG_SYS_MMC_CLK_OD, MMC_DEFAULT_BLKLEN);
>> +#endif
>>   
>>   	return 0;
>>   }
>>   
>> +#ifndef CONFIG_DM_MMC
>>   static const struct mmc_ops atmel_mci_ops = {
>>   	.send_cmd	= mci_send_cmd,
>>   	.set_ios	= mci_set_ios,
>> @@ -456,3 +501,114 @@ int atmel_mci_init(void *regs)
>>   
>>   	return 0;
>>   }
>> +#endif
>> +
>> +#ifdef CONFIG_DM_MMC
>> +static const struct dm_mmc_ops atmel_mci_mmc_ops = {
>> +	.send_cmd = atmel_mci_send_cmd,
>> +	.set_ios = atmel_mci_set_ios,
>> +};
>> +
>> +static void atmel_mci_setup_cfg(struct atmel_mci_priv *priv)
>> +{
>> +	struct mmc_config *cfg;
>> +	u32 version;
>> +
>> +	cfg = &priv->cfg;
>> +	cfg->name = "Atmel mci";
>> +	cfg->voltages = MMC_VDD_32_33 | MMC_VDD_33_34;
>> +
>> +	/*
>> +	 * If the version is above 3.0, the capabilities of the 8-bit
>> +	 * bus width and high speed are supported.
>> +	 */
>> +	version = atmel_mci_get_version(priv->mci);
>> +	if ((version & 0xf00) >= 0x300) {
>> +		cfg->host_caps = MMC_MODE_8BIT |
>> +				 MMC_MODE_HS | MMC_MODE_HS_52MHz;
>> +	}
>> +
>> +	cfg->host_caps |= MMC_MODE_4BIT;
>> +	cfg->b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT;
>> +	cfg->f_min = priv->bus_clk_rate / (2 * 256);
>> +	cfg->f_max = priv->bus_clk_rate / 2;
>> +}
>> +
>> +static int atmel_mci_enable_clk(struct udevice *dev)
>> +{
>> +	struct atmel_mci_priv *priv = dev_get_priv(dev);
>> +	struct clk clk;
>> +	ulong clk_rate;
>> +	int ret = 0;
>> +
>> +	ret = clk_get_by_index(dev, 0, &clk);
>> +	if (ret) {
>> +		ret = -EINVAL;
>> +		goto failed;
>> +	}
>> +
>> +	ret = clk_enable(&clk);
>> +	if (ret)
>> +		goto failed;
>> +
>> +	clk_rate = clk_get_rate(&clk);
>> +	if (!clk_rate) {
>> +		ret = -EINVAL;
>> +		goto failed;
>> +	}
>> +
>> +	priv->bus_clk_rate = clk_rate;
>> +
>> +failed:
>> +	clk_free(&clk);
>> +
>> +	return ret;
>> +}
>> +
>> +static int atmel_mci_probe(struct udevice *dev)
>> +{
>> +	struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev);
>> +	struct atmel_mci_priv *priv = dev_get_priv(dev);
>> +	struct mmc *mmc;
>> +	int ret;
>> +
>> +	ret = atmel_mci_enable_clk(dev);
>> +	if (ret)
>> +		return ret;
>> +
>> +	priv->mci = (struct atmel_mci *)dev_get_addr_ptr(dev);
>> +
>> +	atmel_mci_setup_cfg(priv);
>> +
>> +	mmc = &priv->mmc;
>> +	mmc->cfg = &priv->cfg;
>> +	mmc->dev = dev;
>> +	upriv->mmc = mmc;
>> +
>> +	atmel_mci_hw_init(priv);
>> +
>> +	return 0;
>> +}
>> +
>> +static int atmel_mci_bind(struct udevice *dev)
>> +{
>> +	struct atmel_mci_priv *priv = dev_get_priv(dev);
>> +
>> +	return mmc_bind(dev, &priv->mmc, &priv->cfg);
>> +}
>> +
>> +static const struct udevice_id atmel_mci_ids[] = {
>> +	{ .compatible = "atmel,hsmci" },
>> +	{ }
>> +};
>> +
>> +U_BOOT_DRIVER(atmel_mci) = {
>> +	.name = "atmel-mci",
>> +	.id = UCLASS_MMC,
>> +	.of_match = atmel_mci_ids,
>> +	.bind = atmel_mci_bind,
>> +	.probe = atmel_mci_probe,
>> +	.priv_auto_alloc_size = sizeof(struct atmel_mci_priv),
>> +	.ops = &atmel_mci_mmc_ops,
>> +};
>> +#endif
>>
Best Regards,
Wenyou Yang


More information about the U-Boot mailing list