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.y...@atmel.com>

If Andreas is ok, i will pick this. Otherwise, pick this with my ack.
Let me know, plz.

Acked-by: Jaehoon Chung <jh80.ch...@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
> 

_______________________________________________
U-Boot mailing list
U-Boot@lists.denx.de
https://lists.denx.de/listinfo/u-boot

Reply via email to