Message ID | 1508424362-19649-3-git-send-email-patrice.chotard@st.com |
---|---|
State | Superseded |
Delegated to: | Tom Rini |
Headers | show |
Series | Extend ARM_PL180_MMCI | expand |
On 10/19/2017 11:45 PM, patrice.chotard@st.com wrote: > From: Patrice Chotard <patrice.chotard@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@st.com> > Signed-off-by: Patrice Chotard <patrice.chotard@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. > + host->clock_min = 400000; Ditto. > + 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? > + > struct sdi_registers { > u32 power; /* 0x00*/ > u32 clock; /* 0x04*/ >
Hi Jaehoon On 10/20/2017 03:44 PM, Jaehoon Chung wrote: > On 10/19/2017 11:45 PM, patrice.chotard@st.com wrote: >> From: Patrice Chotard <patrice.chotard@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@st.com> >> Signed-off-by: Patrice Chotard <patrice.chotard@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*/ >> >
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; + host->clock_min = 400000; + 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 + struct sdi_registers { u32 power; /* 0x00*/ u32 clock; /* 0x04*/