Message ID | 20180307055138.331-1-jagan@amarulasolutions.com |
---|---|
State | Changes Requested |
Delegated to: | Jagannadha Sutradharudu Teki |
Headers | show |
Series | [U-Boot,Boards,Need,to,Switch,DM] spi: atmel: Full dm conversion | expand |
On 3/7/2018 1:51 PM, Jagan Teki wrote: > atmel_spi now support dt along with platform data, > respective boards need to switch into dm for the same. > > Signed-off-by: Jagan Teki <jagan@amarulasolutions.com> > --- Indeed. Acked-by: Wenyou Yang <wenyouya@gmail.com> Best Regards, Wenyou Yang > drivers/spi/atmel_spi.c | 294 +++++++---------------------------- > include/dm/platform_data/spi_atmel.h | 17 ++ > 2 files changed, 69 insertions(+), 242 deletions(-) > create mode 100644 include/dm/platform_data/spi_atmel.h > > diff --git a/drivers/spi/atmel_spi.c b/drivers/spi/atmel_spi.c > index 8010ab434c..0bd395bb4a 100644 > --- a/drivers/spi/atmel_spi.c > +++ b/drivers/spi/atmel_spi.c > @@ -12,240 +12,31 @@ > #include <wait_bit.h> > > #include <asm/io.h> > - > #include <asm/arch/clk.h> > #include <asm/arch/hardware.h> > -#ifdef CONFIG_DM_SPI > #include <asm/arch/at91_spi.h> > -#endif > -#ifdef CONFIG_DM_GPIO > #include <asm/gpio.h> > -#endif > + > +#include <dm/platform_data/spi_atmel.h> > > #include "atmel_spi.h" > > DECLARE_GLOBAL_DATA_PTR; > > -#ifndef CONFIG_DM_SPI > - > -static int spi_has_wdrbt(struct atmel_spi_slave *slave) > -{ > - unsigned int ver; > - > - ver = spi_readl(slave, VERSION); > - > - return (ATMEL_SPI_VERSION_REV(ver) >= 0x210); > -} > - > -void spi_init() > -{ > - > -} > - > -struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs, > - unsigned int max_hz, unsigned int mode) > -{ > - struct atmel_spi_slave *as; > - unsigned int scbr; > - u32 csrx; > - void *regs; > - > - if (!spi_cs_is_valid(bus, cs)) > - return NULL; > - > - switch (bus) { > - case 0: > - regs = (void *)ATMEL_BASE_SPI0; > - break; > -#ifdef ATMEL_BASE_SPI1 > - case 1: > - regs = (void *)ATMEL_BASE_SPI1; > - break; > -#endif > -#ifdef ATMEL_BASE_SPI2 > - case 2: > - regs = (void *)ATMEL_BASE_SPI2; > - break; > -#endif > -#ifdef ATMEL_BASE_SPI3 > - case 3: > - regs = (void *)ATMEL_BASE_SPI3; > - break; > -#endif > - default: > - return NULL; > - } > - > - > - scbr = (get_spi_clk_rate(bus) + max_hz - 1) / max_hz; > - if (scbr > ATMEL_SPI_CSRx_SCBR_MAX) > - /* Too low max SCK rate */ > - return NULL; > - if (scbr < 1) > - scbr = 1; > - > - csrx = ATMEL_SPI_CSRx_SCBR(scbr); > - csrx |= ATMEL_SPI_CSRx_BITS(ATMEL_SPI_BITS_8); > - if (!(mode & SPI_CPHA)) > - csrx |= ATMEL_SPI_CSRx_NCPHA; > - if (mode & SPI_CPOL) > - csrx |= ATMEL_SPI_CSRx_CPOL; > - > - as = spi_alloc_slave(struct atmel_spi_slave, bus, cs); > - if (!as) > - return NULL; > - > - as->regs = regs; > - as->mr = ATMEL_SPI_MR_MSTR | ATMEL_SPI_MR_MODFDIS > - | ATMEL_SPI_MR_PCS(~(1 << cs) & 0xf); > - if (spi_has_wdrbt(as)) > - as->mr |= ATMEL_SPI_MR_WDRBT; > - > - spi_writel(as, CSR(cs), csrx); > - > - return &as->slave; > -} > - > -void spi_free_slave(struct spi_slave *slave) > -{ > - struct atmel_spi_slave *as = to_atmel_spi(slave); > - > - free(as); > -} > - > -int spi_claim_bus(struct spi_slave *slave) > -{ > - struct atmel_spi_slave *as = to_atmel_spi(slave); > - > - /* Enable the SPI hardware */ > - spi_writel(as, CR, ATMEL_SPI_CR_SPIEN); > - > - /* > - * Select the slave. This should set SCK to the correct > - * initial state, etc. > - */ > - spi_writel(as, MR, as->mr); > - > - return 0; > -} > - > -void spi_release_bus(struct spi_slave *slave) > -{ > - struct atmel_spi_slave *as = to_atmel_spi(slave); > - > - /* Disable the SPI hardware */ > - spi_writel(as, CR, ATMEL_SPI_CR_SPIDIS); > -} > - > -int spi_xfer(struct spi_slave *slave, unsigned int bitlen, > - const void *dout, void *din, unsigned long flags) > -{ > - struct atmel_spi_slave *as = to_atmel_spi(slave); > - unsigned int len_tx; > - unsigned int len_rx; > - unsigned int len; > - u32 status; > - const u8 *txp = dout; > - u8 *rxp = din; > - u8 value; > - > - if (bitlen == 0) > - /* Finish any previously submitted transfers */ > - goto out; > - > - /* > - * TODO: The controller can do non-multiple-of-8 bit > - * transfers, but this driver currently doesn't support it. > - * > - * It's also not clear how such transfers are supposed to be > - * represented as a stream of bytes...this is a limitation of > - * the current SPI interface. > - */ > - if (bitlen % 8) { > - /* Errors always terminate an ongoing transfer */ > - flags |= SPI_XFER_END; > - goto out; > - } > - > - len = bitlen / 8; > - > - /* > - * The controller can do automatic CS control, but it is > - * somewhat quirky, and it doesn't really buy us much anyway > - * in the context of U-Boot. > - */ > - if (flags & SPI_XFER_BEGIN) { > - spi_cs_activate(slave); > - /* > - * sometimes the RDR is not empty when we get here, > - * in theory that should not happen, but it DOES happen. > - * Read it here to be on the safe side. > - * That also clears the OVRES flag. Required if the > - * following loop exits due to OVRES! > - */ > - spi_readl(as, RDR); > - } > - > - for (len_tx = 0, len_rx = 0; len_rx < len; ) { > - status = spi_readl(as, SR); > - > - if (status & ATMEL_SPI_SR_OVRES) > - return -1; > - > - if (len_tx < len && (status & ATMEL_SPI_SR_TDRE)) { > - if (txp) > - value = *txp++; > - else > - value = 0; > - spi_writel(as, TDR, value); > - len_tx++; > - } > - if (status & ATMEL_SPI_SR_RDRF) { > - value = spi_readl(as, RDR); > - if (rxp) > - *rxp++ = value; > - len_rx++; > - } > - } > - > -out: > - if (flags & SPI_XFER_END) { > - /* > - * Wait until the transfer is completely done before > - * we deactivate CS. > - */ > - do { > - status = spi_readl(as, SR); > - } while (!(status & ATMEL_SPI_SR_TXEMPTY)); > - > - spi_cs_deactivate(slave); > - } > - > - return 0; > -} > - > -#else > - > -#define MAX_CS_COUNT 4 > - > -struct atmel_spi_platdata { > - struct at91_spi *regs; > -}; > - > struct atmel_spi_priv { > + struct at91_spi *regs; > unsigned int freq; /* Default frequency */ > unsigned int mode; > ulong bus_clk_rate; > - struct gpio_desc cs_gpios[MAX_CS_COUNT]; > + struct gpio_desc *cs_gpios; > }; > > static int atmel_spi_claim_bus(struct udevice *dev) > { > struct udevice *bus = dev_get_parent(dev); > - struct atmel_spi_platdata *bus_plat = dev_get_platdata(bus); > struct atmel_spi_priv *priv = dev_get_priv(bus); > - struct dm_spi_slave_platdata *slave_plat = dev_get_parent_platdata(dev); > - struct at91_spi *reg_base = bus_plat->regs; > + struct dm_spi_slave_platdata *slave_plat = > + dev_get_parent_platdata(dev); > u32 cs = slave_plat->cs; > u32 freq = priv->freq; > u32 scbr, csrx, mode; > @@ -265,16 +56,16 @@ static int atmel_spi_claim_bus(struct udevice *dev) > if (priv->mode & SPI_CPOL) > csrx |= ATMEL_SPI_CSRx_CPOL; > > - writel(csrx, ®_base->csr[cs]); > + writel(csrx, &priv->regs->csr[cs]); > > mode = ATMEL_SPI_MR_MSTR | > ATMEL_SPI_MR_MODFDIS | > ATMEL_SPI_MR_WDRBT | > ATMEL_SPI_MR_PCS(~(1 << cs)); > > - writel(mode, ®_base->mr); > + writel(mode, &priv->regs->mr); > > - writel(ATMEL_SPI_CR_SPIEN, ®_base->cr); > + writel(ATMEL_SPI_CR_SPIEN, &priv->regs->cr); > > return 0; > } > @@ -282,9 +73,9 @@ static int atmel_spi_claim_bus(struct udevice *dev) > static int atmel_spi_release_bus(struct udevice *dev) > { > struct udevice *bus = dev_get_parent(dev); > - struct atmel_spi_platdata *bus_plat = dev_get_platdata(bus); > + struct atmel_spi_priv *priv = dev_get_priv(bus); > > - writel(ATMEL_SPI_CR_SPIDIS, &bus_plat->regs->cr); > + writel(ATMEL_SPI_CR_SPIDIS, &priv->regs->cr); > > return 0; > } > @@ -319,8 +110,7 @@ static int atmel_spi_xfer(struct udevice *dev, unsigned int bitlen, > const void *dout, void *din, unsigned long flags) > { > struct udevice *bus = dev_get_parent(dev); > - struct atmel_spi_platdata *bus_plat = dev_get_platdata(bus); > - struct at91_spi *reg_base = bus_plat->regs; > + struct atmel_spi_priv *priv = dev_get_priv(bus); > > u32 len_tx, len_rx, len; > u32 status; > @@ -362,11 +152,11 @@ static int atmel_spi_xfer(struct udevice *dev, unsigned int bitlen, > * That also clears the OVRES flag. Required if the > * following loop exits due to OVRES! > */ > - readl(®_base->rdr); > + readl(&priv->regs->rdr); > } > > for (len_tx = 0, len_rx = 0; len_rx < len; ) { > - status = readl(®_base->sr); > + status = readl(&priv->regs->sr); > > if (status & ATMEL_SPI_SR_OVRES) > return -1; > @@ -376,12 +166,12 @@ static int atmel_spi_xfer(struct udevice *dev, unsigned int bitlen, > value = *txp++; > else > value = 0; > - writel(value, ®_base->tdr); > + writel(value, &priv->regs->tdr); > len_tx++; > } > > if (status & ATMEL_SPI_SR_RDRF) { > - value = readl(®_base->rdr); > + value = readl(&priv->regs->rdr); > if (rxp) > *rxp++ = value; > len_rx++; > @@ -394,7 +184,7 @@ out: > * Wait until the transfer is completely done before > * we deactivate CS. > */ > - wait_for_bit_le32(®_base->sr, > + wait_for_bit_le32(&priv->regs->sr, > ATMEL_SPI_SR_TXEMPTY, true, 1000, false); > > atmel_spi_cs_deactivate(dev); > @@ -461,23 +251,17 @@ static int atmel_spi_enable_clk(struct udevice *bus) > > static int atmel_spi_probe(struct udevice *bus) > { > - struct atmel_spi_platdata *bus_plat = dev_get_platdata(bus); > + struct atmel_spi_platdata *plat = dev_get_platdata(bus); > struct atmel_spi_priv *priv = dev_get_priv(bus); > int i, ret; > > + priv->regs = plat->regs; > + priv->cs_gpios = plat->cs_gpios; > + > ret = atmel_spi_enable_clk(bus); > if (ret) > return ret; > - > - bus_plat->regs = (struct at91_spi *)devfdt_get_addr(bus); > - > - ret = gpio_request_list_by_name(bus, "cs-gpios", priv->cs_gpios, > - ARRAY_SIZE(priv->cs_gpios), 0); > - if (ret < 0) { > - pr_err("Can't get %s gpios! Error: %d", bus->name, ret); > - return ret; > - } > - > + > for(i = 0; i < ARRAY_SIZE(priv->cs_gpios); i++) { > if (!dm_gpio_is_valid(&priv->cs_gpios[i])) > continue; > @@ -486,7 +270,30 @@ static int atmel_spi_probe(struct udevice *bus) > GPIOD_IS_OUT | GPIOD_IS_OUT_ACTIVE); > } > > - writel(ATMEL_SPI_CR_SWRST, &bus_plat->regs->cr); > + writel(ATMEL_SPI_CR_SWRST, &priv->regs->cr); > + > + return 0; > +} > + > +#if CONFIG_IS_ENABLED(OF_CONTROL) > +static int atmel_ofdata_to_platadata(struct udevice *bus) > +{ > + struct atmel_spi_platdata *plat = bus->platdata; > + fdt_addr_t addr; > + int ret; > + > + addr = devfdt_get_addr(bus); > + if (addr == FDT_ADDR_T_NONE) > + return -EINVAL; > + > + plat->regs = (struct at91_spi *)addr; > + > + ret = gpio_request_list_by_name(bus, "cs-gpios", plat->cs_gpios, > + ARRAY_SIZE(plat->cs_gpios), 0); > + if (ret < 0) { > + pr_err("Can't get %s gpios! Error: %d", bus->name, ret); > + return ret; > + } > > return 0; > } > @@ -495,14 +302,17 @@ static const struct udevice_id atmel_spi_ids[] = { > { .compatible = "atmel,at91rm9200-spi" }, > { } > }; > +#endif > > U_BOOT_DRIVER(atmel_spi) = { > .name = "atmel_spi", > .id = UCLASS_SPI, > +#if CONFIG_IS_ENABLED(OF_CONTROL) > .of_match = atmel_spi_ids, > - .ops = &atmel_spi_ops, > + .ofdata_to_platdata = atmel_ofdata_to_platadata, > .platdata_auto_alloc_size = sizeof(struct atmel_spi_platdata), > - .priv_auto_alloc_size = sizeof(struct atmel_spi_priv), > +#endif > .probe = atmel_spi_probe, > + .ops = &atmel_spi_ops, > + .priv_auto_alloc_size = sizeof(struct atmel_spi_priv), > }; > -#endif > diff --git a/include/dm/platform_data/spi_atmel.h b/include/dm/platform_data/spi_atmel.h > new file mode 100644 > index 0000000000..a5bb5665a3 > --- /dev/null > +++ b/include/dm/platform_data/spi_atmel.h > @@ -0,0 +1,17 @@ > +/* > + * Copyright (C) 2018 Jagan Teki <jagan@amarulasolutions.com> > + * > + * SPDX-License-Identifier: GPL-2.0+ > + */ > + > +#ifndef __spi_atmel_h > +#define __spi_atmel_h > + > +#define MAX_CS_COUNT 4 > + > +struct atmel_spi_platdata { > + struct at91_spi *regs; > + struct gpio_desc cs_gpios[MAX_CS_COUNT]; > +}; > + > +#endif /* __spi_atmel_h */
On Tue, Mar 13, 2018 at 10:57 AM, Wenyou Yang <wenyouya@gmail.com> wrote: > On 3/7/2018 1:51 PM, Jagan Teki wrote: >> >> atmel_spi now support dt along with platform data, >> respective boards need to switch into dm for the same. >> >> Signed-off-by: Jagan Teki <jagan@amarulasolutions.com> >> --- > > Indeed. Look like there are very few boards need to move DM as well as DM_SPI to use this driver. # grep -R CONFIG_ATMEL_SPI include/configs/ include/configs/snapper9g45.h:#define CONFIG_ATMEL_SPI include/configs/ma5d4evk.h:#define CONFIG_ATMEL_SPI include/configs/ma5d4evk.h:#define CONFIG_ATMEL_SPI0 include/configs/taurus.h:#define CONFIG_ATMEL_SPI include/configs/vinco.h:#define CONFIG_ATMEL_SPI include/configs/vinco.h:#define CONFIG_ATMEL_SPI0 Added respective board maintainers on the list, hope this these will move to DM.
diff --git a/drivers/spi/atmel_spi.c b/drivers/spi/atmel_spi.c index 8010ab434c..0bd395bb4a 100644 --- a/drivers/spi/atmel_spi.c +++ b/drivers/spi/atmel_spi.c @@ -12,240 +12,31 @@ #include <wait_bit.h> #include <asm/io.h> - #include <asm/arch/clk.h> #include <asm/arch/hardware.h> -#ifdef CONFIG_DM_SPI #include <asm/arch/at91_spi.h> -#endif -#ifdef CONFIG_DM_GPIO #include <asm/gpio.h> -#endif + +#include <dm/platform_data/spi_atmel.h> #include "atmel_spi.h" DECLARE_GLOBAL_DATA_PTR; -#ifndef CONFIG_DM_SPI - -static int spi_has_wdrbt(struct atmel_spi_slave *slave) -{ - unsigned int ver; - - ver = spi_readl(slave, VERSION); - - return (ATMEL_SPI_VERSION_REV(ver) >= 0x210); -} - -void spi_init() -{ - -} - -struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs, - unsigned int max_hz, unsigned int mode) -{ - struct atmel_spi_slave *as; - unsigned int scbr; - u32 csrx; - void *regs; - - if (!spi_cs_is_valid(bus, cs)) - return NULL; - - switch (bus) { - case 0: - regs = (void *)ATMEL_BASE_SPI0; - break; -#ifdef ATMEL_BASE_SPI1 - case 1: - regs = (void *)ATMEL_BASE_SPI1; - break; -#endif -#ifdef ATMEL_BASE_SPI2 - case 2: - regs = (void *)ATMEL_BASE_SPI2; - break; -#endif -#ifdef ATMEL_BASE_SPI3 - case 3: - regs = (void *)ATMEL_BASE_SPI3; - break; -#endif - default: - return NULL; - } - - - scbr = (get_spi_clk_rate(bus) + max_hz - 1) / max_hz; - if (scbr > ATMEL_SPI_CSRx_SCBR_MAX) - /* Too low max SCK rate */ - return NULL; - if (scbr < 1) - scbr = 1; - - csrx = ATMEL_SPI_CSRx_SCBR(scbr); - csrx |= ATMEL_SPI_CSRx_BITS(ATMEL_SPI_BITS_8); - if (!(mode & SPI_CPHA)) - csrx |= ATMEL_SPI_CSRx_NCPHA; - if (mode & SPI_CPOL) - csrx |= ATMEL_SPI_CSRx_CPOL; - - as = spi_alloc_slave(struct atmel_spi_slave, bus, cs); - if (!as) - return NULL; - - as->regs = regs; - as->mr = ATMEL_SPI_MR_MSTR | ATMEL_SPI_MR_MODFDIS - | ATMEL_SPI_MR_PCS(~(1 << cs) & 0xf); - if (spi_has_wdrbt(as)) - as->mr |= ATMEL_SPI_MR_WDRBT; - - spi_writel(as, CSR(cs), csrx); - - return &as->slave; -} - -void spi_free_slave(struct spi_slave *slave) -{ - struct atmel_spi_slave *as = to_atmel_spi(slave); - - free(as); -} - -int spi_claim_bus(struct spi_slave *slave) -{ - struct atmel_spi_slave *as = to_atmel_spi(slave); - - /* Enable the SPI hardware */ - spi_writel(as, CR, ATMEL_SPI_CR_SPIEN); - - /* - * Select the slave. This should set SCK to the correct - * initial state, etc. - */ - spi_writel(as, MR, as->mr); - - return 0; -} - -void spi_release_bus(struct spi_slave *slave) -{ - struct atmel_spi_slave *as = to_atmel_spi(slave); - - /* Disable the SPI hardware */ - spi_writel(as, CR, ATMEL_SPI_CR_SPIDIS); -} - -int spi_xfer(struct spi_slave *slave, unsigned int bitlen, - const void *dout, void *din, unsigned long flags) -{ - struct atmel_spi_slave *as = to_atmel_spi(slave); - unsigned int len_tx; - unsigned int len_rx; - unsigned int len; - u32 status; - const u8 *txp = dout; - u8 *rxp = din; - u8 value; - - if (bitlen == 0) - /* Finish any previously submitted transfers */ - goto out; - - /* - * TODO: The controller can do non-multiple-of-8 bit - * transfers, but this driver currently doesn't support it. - * - * It's also not clear how such transfers are supposed to be - * represented as a stream of bytes...this is a limitation of - * the current SPI interface. - */ - if (bitlen % 8) { - /* Errors always terminate an ongoing transfer */ - flags |= SPI_XFER_END; - goto out; - } - - len = bitlen / 8; - - /* - * The controller can do automatic CS control, but it is - * somewhat quirky, and it doesn't really buy us much anyway - * in the context of U-Boot. - */ - if (flags & SPI_XFER_BEGIN) { - spi_cs_activate(slave); - /* - * sometimes the RDR is not empty when we get here, - * in theory that should not happen, but it DOES happen. - * Read it here to be on the safe side. - * That also clears the OVRES flag. Required if the - * following loop exits due to OVRES! - */ - spi_readl(as, RDR); - } - - for (len_tx = 0, len_rx = 0; len_rx < len; ) { - status = spi_readl(as, SR); - - if (status & ATMEL_SPI_SR_OVRES) - return -1; - - if (len_tx < len && (status & ATMEL_SPI_SR_TDRE)) { - if (txp) - value = *txp++; - else - value = 0; - spi_writel(as, TDR, value); - len_tx++; - } - if (status & ATMEL_SPI_SR_RDRF) { - value = spi_readl(as, RDR); - if (rxp) - *rxp++ = value; - len_rx++; - } - } - -out: - if (flags & SPI_XFER_END) { - /* - * Wait until the transfer is completely done before - * we deactivate CS. - */ - do { - status = spi_readl(as, SR); - } while (!(status & ATMEL_SPI_SR_TXEMPTY)); - - spi_cs_deactivate(slave); - } - - return 0; -} - -#else - -#define MAX_CS_COUNT 4 - -struct atmel_spi_platdata { - struct at91_spi *regs; -}; - struct atmel_spi_priv { + struct at91_spi *regs; unsigned int freq; /* Default frequency */ unsigned int mode; ulong bus_clk_rate; - struct gpio_desc cs_gpios[MAX_CS_COUNT]; + struct gpio_desc *cs_gpios; }; static int atmel_spi_claim_bus(struct udevice *dev) { struct udevice *bus = dev_get_parent(dev); - struct atmel_spi_platdata *bus_plat = dev_get_platdata(bus); struct atmel_spi_priv *priv = dev_get_priv(bus); - struct dm_spi_slave_platdata *slave_plat = dev_get_parent_platdata(dev); - struct at91_spi *reg_base = bus_plat->regs; + struct dm_spi_slave_platdata *slave_plat = + dev_get_parent_platdata(dev); u32 cs = slave_plat->cs; u32 freq = priv->freq; u32 scbr, csrx, mode; @@ -265,16 +56,16 @@ static int atmel_spi_claim_bus(struct udevice *dev) if (priv->mode & SPI_CPOL) csrx |= ATMEL_SPI_CSRx_CPOL; - writel(csrx, ®_base->csr[cs]); + writel(csrx, &priv->regs->csr[cs]); mode = ATMEL_SPI_MR_MSTR | ATMEL_SPI_MR_MODFDIS | ATMEL_SPI_MR_WDRBT | ATMEL_SPI_MR_PCS(~(1 << cs)); - writel(mode, ®_base->mr); + writel(mode, &priv->regs->mr); - writel(ATMEL_SPI_CR_SPIEN, ®_base->cr); + writel(ATMEL_SPI_CR_SPIEN, &priv->regs->cr); return 0; } @@ -282,9 +73,9 @@ static int atmel_spi_claim_bus(struct udevice *dev) static int atmel_spi_release_bus(struct udevice *dev) { struct udevice *bus = dev_get_parent(dev); - struct atmel_spi_platdata *bus_plat = dev_get_platdata(bus); + struct atmel_spi_priv *priv = dev_get_priv(bus); - writel(ATMEL_SPI_CR_SPIDIS, &bus_plat->regs->cr); + writel(ATMEL_SPI_CR_SPIDIS, &priv->regs->cr); return 0; } @@ -319,8 +110,7 @@ static int atmel_spi_xfer(struct udevice *dev, unsigned int bitlen, const void *dout, void *din, unsigned long flags) { struct udevice *bus = dev_get_parent(dev); - struct atmel_spi_platdata *bus_plat = dev_get_platdata(bus); - struct at91_spi *reg_base = bus_plat->regs; + struct atmel_spi_priv *priv = dev_get_priv(bus); u32 len_tx, len_rx, len; u32 status; @@ -362,11 +152,11 @@ static int atmel_spi_xfer(struct udevice *dev, unsigned int bitlen, * That also clears the OVRES flag. Required if the * following loop exits due to OVRES! */ - readl(®_base->rdr); + readl(&priv->regs->rdr); } for (len_tx = 0, len_rx = 0; len_rx < len; ) { - status = readl(®_base->sr); + status = readl(&priv->regs->sr); if (status & ATMEL_SPI_SR_OVRES) return -1; @@ -376,12 +166,12 @@ static int atmel_spi_xfer(struct udevice *dev, unsigned int bitlen, value = *txp++; else value = 0; - writel(value, ®_base->tdr); + writel(value, &priv->regs->tdr); len_tx++; } if (status & ATMEL_SPI_SR_RDRF) { - value = readl(®_base->rdr); + value = readl(&priv->regs->rdr); if (rxp) *rxp++ = value; len_rx++; @@ -394,7 +184,7 @@ out: * Wait until the transfer is completely done before * we deactivate CS. */ - wait_for_bit_le32(®_base->sr, + wait_for_bit_le32(&priv->regs->sr, ATMEL_SPI_SR_TXEMPTY, true, 1000, false); atmel_spi_cs_deactivate(dev); @@ -461,23 +251,17 @@ static int atmel_spi_enable_clk(struct udevice *bus) static int atmel_spi_probe(struct udevice *bus) { - struct atmel_spi_platdata *bus_plat = dev_get_platdata(bus); + struct atmel_spi_platdata *plat = dev_get_platdata(bus); struct atmel_spi_priv *priv = dev_get_priv(bus); int i, ret; + priv->regs = plat->regs; + priv->cs_gpios = plat->cs_gpios; + ret = atmel_spi_enable_clk(bus); if (ret) return ret; - - bus_plat->regs = (struct at91_spi *)devfdt_get_addr(bus); - - ret = gpio_request_list_by_name(bus, "cs-gpios", priv->cs_gpios, - ARRAY_SIZE(priv->cs_gpios), 0); - if (ret < 0) { - pr_err("Can't get %s gpios! Error: %d", bus->name, ret); - return ret; - } - + for(i = 0; i < ARRAY_SIZE(priv->cs_gpios); i++) { if (!dm_gpio_is_valid(&priv->cs_gpios[i])) continue; @@ -486,7 +270,30 @@ static int atmel_spi_probe(struct udevice *bus) GPIOD_IS_OUT | GPIOD_IS_OUT_ACTIVE); } - writel(ATMEL_SPI_CR_SWRST, &bus_plat->regs->cr); + writel(ATMEL_SPI_CR_SWRST, &priv->regs->cr); + + return 0; +} + +#if CONFIG_IS_ENABLED(OF_CONTROL) +static int atmel_ofdata_to_platadata(struct udevice *bus) +{ + struct atmel_spi_platdata *plat = bus->platdata; + fdt_addr_t addr; + int ret; + + addr = devfdt_get_addr(bus); + if (addr == FDT_ADDR_T_NONE) + return -EINVAL; + + plat->regs = (struct at91_spi *)addr; + + ret = gpio_request_list_by_name(bus, "cs-gpios", plat->cs_gpios, + ARRAY_SIZE(plat->cs_gpios), 0); + if (ret < 0) { + pr_err("Can't get %s gpios! Error: %d", bus->name, ret); + return ret; + } return 0; } @@ -495,14 +302,17 @@ static const struct udevice_id atmel_spi_ids[] = { { .compatible = "atmel,at91rm9200-spi" }, { } }; +#endif U_BOOT_DRIVER(atmel_spi) = { .name = "atmel_spi", .id = UCLASS_SPI, +#if CONFIG_IS_ENABLED(OF_CONTROL) .of_match = atmel_spi_ids, - .ops = &atmel_spi_ops, + .ofdata_to_platdata = atmel_ofdata_to_platadata, .platdata_auto_alloc_size = sizeof(struct atmel_spi_platdata), - .priv_auto_alloc_size = sizeof(struct atmel_spi_priv), +#endif .probe = atmel_spi_probe, + .ops = &atmel_spi_ops, + .priv_auto_alloc_size = sizeof(struct atmel_spi_priv), }; -#endif diff --git a/include/dm/platform_data/spi_atmel.h b/include/dm/platform_data/spi_atmel.h new file mode 100644 index 0000000000..a5bb5665a3 --- /dev/null +++ b/include/dm/platform_data/spi_atmel.h @@ -0,0 +1,17 @@ +/* + * Copyright (C) 2018 Jagan Teki <jagan@amarulasolutions.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef __spi_atmel_h +#define __spi_atmel_h + +#define MAX_CS_COUNT 4 + +struct atmel_spi_platdata { + struct at91_spi *regs; + struct gpio_desc cs_gpios[MAX_CS_COUNT]; +}; + +#endif /* __spi_atmel_h */
atmel_spi now support dt along with platform data, respective boards need to switch into dm for the same. Signed-off-by: Jagan Teki <jagan@amarulasolutions.com> --- drivers/spi/atmel_spi.c | 294 +++++++---------------------------- include/dm/platform_data/spi_atmel.h | 17 ++ 2 files changed, 69 insertions(+), 242 deletions(-) create mode 100644 include/dm/platform_data/spi_atmel.h