dm: at91: Add driver model support for the spi driver
Subsystems (2)
PATCH v7 1/1 dm: at91: Add driver model support for the spi driver
Add driver model support 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.
---
Changes in v7:
- Move gpio_request_list_by_name() to _probe(), remove *_ofdata_to_platdata().
Changes in v6:
- Remove the two flash related options.
Changes in v5:
- Change clk_client.h -> clk.h to adapt to clk API conversion.
Changes in v4:
- Collect Reviewed-by tag.
- Update the clk API based on [PATCH] clk: convert API to match reset/mailbox fstyle (http://patchwork.ozlabs.org/patch/625342/).
- Remove check on dev_get_parent() return.
- Fixed the return value, -ENODEV->-EINVAL.
- Retain #include <asm/arch/clk.h> line.
Changes in v3:
- Remove redundant log print.
Changes in v2:
- Add clock support.
drivers/spi/Kconfig | 7 ++ drivers/spi/atmel_spi.c | 295 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 302 insertions(+)
drivers/spi/Kconfig +7 -0
@@ -32,6 +32,13 @@ config ATH79_SPI uses driver model and requires a device tree binding to operate. please refer to doc/device-tree-bindings/spi/spi-ath79.txt. +config ATMEL_SPI + bool "Atmel SPI driver" + depends on ARCH_AT91 + help + Enable the Atmel SPI driver. This driver can be used to access + the SPI Flash, such as AT25DF321. + config CADENCE_QSPI bool "Cadence QSPI driver" help
drivers/spi/atmel_spi.c +295 -0
313 lines not on this page · raw message
Signature · 1 line
2.7.4
PATCH v7 1/1 dm: at91: Add driver model support for the spi driver
Hello Wenyou,
Am 29.07.2016 um 02:38 schrieb Wenyou Yang:
Quoted 29 lines
Add driver model support 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 <[email protected]>Reviewed-by Simon Glass <[email protected]>---
Changes in v7:
- Movegpio_request_list_by_name()to_probe(), remove*_ofdata_to_platdata().Changes in v6:
- Remove the two flash related options.Changes in v5:
- Changeclk_client.h->clk.hto adapt to clk API conversion.Changes in v4:
- Collect Reviewed-by tag.
- Update the clk API based on [PATCH] clk: convert API to matchreset/mailbox fstyle (http://patchwork.ozlabs.org/patch/625342/).- Remove check on
dev_get_parent()return.
- Fixed the return value, -ENODEV->-EINVAL.
- Retain #include <asm/arch/clk.h> line.Changes in v3:
- Remove redundant log print.
Quoted 6 lines
Changes in v2:
- Add clock support.drivers/spi/Kconfig | 7 ++ drivers/spi/atmel_spi.c | 295 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 302 insertions(+)
bye,
Heiko
Quoted 340 lines
drivers/spi/Kconfig +7
-0@@ -32,6 +32,13 @@ config ATH79_SPI uses driver model and requires a device tree binding to operate. please refer to doc/device-tree-bindings/spi/spi-ath79.txt. +config ATMEL_SPI + bool "Atmel SPI driver" + depends on ARCH_AT91 + help + Enable the Atmel SPI driver. This driver can be used to access + the SPI Flash, such as AT25DF321. + config CADENCE_QSPI bool "Cadence QSPI driver" helpdrivers/spi/atmel_spi.c +295
-0@@ -4,6 +4,9 @@* SPDX-License-Identifier: GPL-2.0+ */ #include <common.h> +#include <clk.h> +#include <dm.h> +#include <fdtdec.h> #include <spi.h> #include <malloc.h> @@ -11,9 +14,15 @@#include <asm/arch/clk.h> #include <asm/arch/hardware.h> +#include <asm/arch/at91_spi.h> +#include <asm/gpio.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;@@ -209,3 +218,289 @@ out:return 0 ; } + +#else + +#define MAX_CS_COUNT 4 + +struct atmel_spi_platdata { +struct at91_spi *regs; +}; + +struct atmel_spi_priv { +unsigned int freq;/* Default frequency */ +unsigned int mode; +ulong bus_clk_rate; +struct gpio_desc cs_gpios[MAX_CS_COUNT ]; +}; + +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; +u32 cs = slave_plat->cs; +u32 freq = priv->freq; +u32 scbr, csrx, mode; + + scbr = (priv->bus_clk_rate + freq -1 ) / freq; +if (scbr > ATMEL_SPI_CSRx_SCBR_MAX) +return -EINVAL ; + +if (scbr <1 ) + scbr =1 ; + + csrx =ATMEL_SPI_CSRx_SCBR (scbr); + csrx |=ATMEL_SPI_CSRx_BITS (ATMEL_SPI_BITS_8 ); + +if (!(priv->mode &SPI_CPHA )) + csrx |= ATMEL_SPI_CSRx_NCPHA; +if (priv->mode &SPI_CPOL ) + csrx |= ATMEL_SPI_CSRx_CPOL; + +writel (csrx, ®_base->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 (ATMEL_SPI_CR_SPIEN , ®_base->cr); + +return 0 ; +} + +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); + +writel (ATMEL_SPI_CR_SPIDIS , &bus_plat->regs->cr); + +return 0 ; +} + +static void atmel_spi_cs_activate (struct udevice *dev) +{ +struct udevice *bus =dev_get_parent (dev); +struct atmel_spi_priv *priv =dev_get_priv (bus); +struct dm_spi_slave_platdata *slave_plat =dev_get_parent_platdata (dev); +u32 cs = slave_plat->cs; + +dm_gpio_set_value (&priv->cs_gpios[cs],0 ); +} + +static void atmel_spi_cs_deactivate (struct udevice *dev) +{ +struct udevice *bus =dev_get_parent (dev); +struct atmel_spi_priv *priv =dev_get_priv (bus); +struct dm_spi_slave_platdata *slave_plat =dev_get_parent_platdata (dev); +u32 cs = slave_plat->cs; + +dm_gpio_set_value (&priv->cs_gpios[cs],1 ); +} + +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; + +u32 len_tx, len_rx, len; +u32 status; +const u8 *txp = dout; +u8 *rxp = din; +u8 value; + +if (bitlen ==0 ) + goto out; + +/* +* 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 ) { +atmel_spi_cs_activate (dev); + +/* +* 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! +*/ +readl (®_base->rdr); + } + +for (len_tx =0 , len_rx =0 ; len_rx < len; ) { + status =readl (®_base->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 ; +writel (value, ®_base->tdr); + len_tx++; + } + +if (status &ATMEL_SPI_SR_RDRF ) { + value =readl (®_base->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 =readl (®_base->sr); + }while (!(status &ATMEL_SPI_SR_TXEMPTY )); + +atmel_spi_cs_deactivate (dev); + } + +return 0 ; +} + +static int atmel_spi_set_speed (struct udevice *bus,uint speed) +{ +struct atmel_spi_priv *priv =dev_get_priv (bus); + + priv->freq = speed; + +return 0 ; +} + +static int atmel_spi_set_mode (struct udevice *bus,uint mode) +{ +struct atmel_spi_priv *priv =dev_get_priv (bus); + + priv->mode = mode; + +return 0 ; +} + +static const struct dm_spi_ops atmel_spi_ops = { + .claim_bus = atmel_spi_claim_bus, + .release_bus = atmel_spi_release_bus, + .xfer = atmel_spi_xfer, + .set_speed = atmel_spi_set_speed, + .set_mode = atmel_spi_set_mode, +/* +* cs_info is not needed, since we require all chip selects to be +* in the device tree explicitly +*/ +}; + +static int atmel_spi_enable_clk (struct udevice *bus) +{ +struct atmel_spi_priv *priv =dev_get_priv (bus); +struct udevice *dev_clk; +struct clk clk; +ulong clk_rate; +int periph; +int ret; + + ret =clk_get_by_index (bus,0 , &clk); +if (ret) +return -EINVAL ; + + periph =fdtdec_get_uint (gd->fdt_blob, clk.dev->of_offset,"reg" ,-1 ); +if (periph <0 ) +return -EINVAL ; + + dev_clk =dev_get_parent (clk.dev); + ret =clk_request (dev_clk, &clk); +if (ret) +return ret; + + clk.id = periph; + ret =clk_enable (&clk); +if (ret) +return ret; + + ret =clk_get_by_index (dev_clk,0 , &clk); +if (ret) +return ret; + + clk_rate =clk_get_rate (&clk); +if (!clk_rate) +return -EINVAL ; + + priv->bus_clk_rate = clk_rate; + +clk_free (&clk); + +return 0 ; +} + +static int atmel_spi_probe (struct udevice *bus) +{ +struct atmel_spi_platdata *bus_plat =dev_get_platdata (bus); +struct atmel_spi_priv *priv =dev_get_priv (bus); +int ret; + + ret =atmel_spi_enable_clk (bus); +if (ret) +return ret; + + bus_plat->regs = (struct at91_spi *)dev_get_addr (bus); + + ret =gpio_request_list_by_name (bus,"cs-gpios" , priv->cs_gpios, +ARRAY_SIZE (priv->cs_gpios),0 ); +if (ret <0 ) { +error ("Can't get %s gpios! Error: %d" , bus->name, ret); +return ret; + } + +writel (ATMEL_SPI_CR_SWRST , &bus_plat->regs->cr); + +return 0 ; +} + +static const struct udevice_id atmel_spi_ids[] = { + { .compatible ="atmel,at91rm9200-spi" }, + { } +}; + +U_BOOT_DRIVER (atmel_spi) = { + .name ="atmel_spi" , + .id =UCLASS_SPI , + .of_match = atmel_spi_ids, + .ops = &atmel_spi_ops, + .platdata_auto_alloc_size =sizeof (struct atmel_spi_platdata ), + .priv_auto_alloc_size =sizeof (struct atmel_spi_priv ), + .probe = atmel_spi_probe, +}; +#endif
Signature · 2 lines
DENX Software Engineering GmbH, Managing Director: Wolfgang Denk HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
PATCH v7 1/1 dm: at91: Add driver model support for the spi driver
Quoted 37 lines · Heiko Schocher
Hello Wenyou,
Am 29.07.2016 um 02:38 schrieb Wenyou Yang:
Quoted 33 lines
Add driver model support 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 <[email protected]>Reviewed-by Simon Glass <[email protected]>---
Changes in v7:
- Movegpio_request_list_by_name()to_probe(), remove*_ofdata_to_platdata().Changes in v6:
- Remove the two flash related options.Changes in v5:
- Changeclk_client.h->clk.hto adapt to clk API conversion.Changes in v4:
- Collect Reviewed-by tag.
- Update the clk API based on [PATCH] clk: convert API to matchreset/mailbox fstyle (http://patchwork.ozlabs.org/patch/625342/).- Remove check on
dev_get_parent()return.
- Fixed the return value, -ENODEV->-EINVAL.
- Retain #include <asm/arch/clk.h> line.Changes in v3:
- Remove redundant log print.Changes in v2:
- Add clock support.
Quoted 7 lines
Quoted 4 lines
drivers/spi/Kconfig | 7 ++ drivers/spi/atmel_spi.c | 295 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 302 insertions(+)Reviewed-by Heiko Schocher <[email protected]>
Signature · 1 line
Jagan.
PATCH v7 1/1 dm: at91: Add driver model support for the spi driver
In reply to Wenyou YangQuoted 7 lines · Wenyou Yang
Add driver model support 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 <[email protected]>Reviewed-by Simon Glass <[email protected]>---
Applied to u-boot-spi/master
Signature · 1 line
Jagan.
PATCH v7 1/1 dm: at91: Add driver model support for the spi driver
Quoted 4 lines · Jagan Teki
Quoted 3 lines · Wenyou Yang
Add driver model support 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.
Need some info - how many boards still pending to use this driver to use it in dm?
Signature · 1 line
Jagan.
PATCH v7 1/1 dm: at91: Add driver model support for the spi driver
Hi Jagan,
Quoted 8 lines
-----Original Message-----
From: Jagan Teki [mailto:jagannadh.teki at gmail.com]
Sent: 2016?8?6? 21:00
To: Wenyou Yang <[email protected]>
Cc: U-Boot Mailing List <[email protected]>
Subject: Re: [U-Boot] [PATCH v7] dm: at91: Add driver model support for the spi driver
Quoted 7 lines
Quoted 4 lines · Jagan Teki
Quoted 3 lines · Wenyou Yang
Add driver model support 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.
Need some info - how many boards still pending to use this driver to use it in dm?
For now, only sama5d2_xplained has used this drive in dm, other boards with AT91 SoC has not used dm driver, such as at91sam9g20ek, at91sam9x5ek, at91sam9m10g45ek, sama5d3xek. sama5d4ek, ....
Best Regards,
Wenyou Yang
PATCH v7 1/1 dm: at91: Add driver model support for the spi driver
Quoted 12 lines · On 8 August 2016 at 06:14, <[email protected]> wrote:
Hi Jagan,
Quoted 10 lines
-----Original Message-----
From: Jagan Teki [mailto:jagannadh.teki at gmail.com]
Sent: 2016?8?6? 21:00
To: Wenyou Yang <[email protected]>
Cc: U-Boot Mailing List <[email protected]>
Subject: Re: [U-Boot] [PATCH v7] dm: at91: Add driver model support for the spi driverQuoted 1 line · Jagan Teki
On 29 July 2016 at 06:08, Wenyou Yang <[email protected]> wrote:
Quoted 8 lines
Quoted 5 lines
Quoted 3 lines
Quoted 3 lines
Add driver model support 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.
Need some info - how many boards still pending to use this driver to use it in dm?
For now, only
sama5d2_xplainedhas used this drive in dm, other boards with AT91 SoC has not used dm driver, such as at91sam9g20ek, at91sam9x5ek, at91sam9m10g45ek, sama5d3xek. sama5d4ek, ....
Please convert these boards to dm as well, because driver still have non-dm code never know when it gets removed.
thanks!
Signature · 1 line
Jagan.
A message that is not in the archive (sent off-list or not yet received): [email protected]
A message that is not in the archive (sent off-list or not yet received): CAD6G_RSf3n-wYHAZ1MYgkLLY6HhD1MDP23gXaG50HO5P1RFhWA@mail.gmail.com
PATCH v7 1/1 dm: at91: Add driver model support for the spi driver
Hi Jagan,
Quoted 52 lines · Jagan Teki
Hi Andreas,
Quoted 48 lines · Andreas Bie?mann
Hi Jagan,
Quoted 34 lines · Jagan Teki
Quoted 25 lines · On 8 August 2016 at 06:14, <[email protected]> wrote:
Hi Jagan,
Quoted 12 lines
-----Original Message-----
From: Jagan Teki [mailto:jagannadh.teki at gmail.com]
Sent: 2016?8?6? 21:00
To: Wenyou Yang <[email protected]>
Cc: U-Boot Mailing List <[email protected]>
Subject: Re: [U-Boot] [PATCH v7] dm: at91: Add driver model support for
the spi
driverOn 31 July 2016 at 17:05, Jagan Teki <[email protected]> wrote:
Quoted 8 lines
Quoted 4 lines · Wenyou Yang
Quoted 3 lines
Add driver model support 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.
Need some info - how many boards still pending to use this driver to use
it in dm?Quoted 5 lines
For now, only
sama5d2_xplainedhas used this drive in dm, other boards
with AT91 SoC has not used dm driver,
such as at91sam9g20ek, at91sam9x5ek, at91sam9m10g45ek, sama5d3xek. sama5d4ek, ....Quoted 2 lines
Please convert these boards to dm as well, because driver still have non-dm code never know when it gets removed.
non-dm code has to live for some time since this is a shared driver for
avr32 and arm architecture of atmel SoC. Unfortunately avr32 still lacks dm
support in u-boot. I have some prepared patches but AFAIR there was a problem with early malloc ... after that I had no time to get it done.
Quoted 8 lines
Quoted 5 lines
Beside that I also insist on converting the remaining at91 boards to dm.
Since there are some boards I would suggest a time frame until end of this
year.OK, look like avr32 should be a blocker here since at91 boards can do at-least. What is the plan on avr32, shall I look in to it?
I hope I can look for it in next couple of month. So v2016.11 should be doable, maybe v2017.01. Do you have some avr32 hardware to verify it?
Andreas
Quoted 2 lines
thanks!
PATCH v7 1/1 dm: at91: Add driver model support for the spi driver
Quoted 65 lines · Andreas Bie?mann
Hi Jagan,
Quoted 61 lines · Jagan Teki
Hi Andreas,
Quoted 55 lines · Andreas Bie?mann
Hi Jagan,
Quoted 36 lines · Jagan Teki
Quoted 26 lines · On 8 August 2016 at 06:14, <[email protected]> wrote:
Hi Jagan,
Quoted 11 lines
-----Original Message-----
From: Jagan Teki [mailto:jagannadh.teki at gmail.com]
Sent: 2016?8?6? 21:00
To: Wenyou Yang <[email protected]>
Cc: U-Boot Mailing List <[email protected]>
Subject: Re: [U-Boot] [PATCH v7] dm: at91: Add driver model support for
the spi
driverOn 31 July 2016 at 17:05, Jagan Teki <[email protected]> wrote:
Quoted 8 lines
Quoted 4 lines · Wenyou Yang
Quoted 3 lines
Add driver model support 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.
Need some info - how many boards still pending to use this driver to use
it in dm?Quoted 4 lines
For now, only
sama5d2_xplainedhas used this drive in dm, other boards with AT91 SoC has not used dm driver,
such as at91sam9g20ek, at91sam9x5ek, at91sam9m10g45ek, sama5d3xek. sama5d4ek, ....Quoted 2 lines
Please convert these boards to dm as well, because driver still have non-dm code never know when it gets removed.
non-dm code has to live for some time since this is a shared driver for avr32 and arm architecture of atmel SoC. Unfortunately avr32 still lacks dm
support in u-boot. I have some prepared patches but AFAIR there was a problem with early malloc ... after that I had no time to get it done.Beside that I also insist on converting the remaining at91 boards to dm. Since there are some boards I would suggest a time frame until end of this
year.
Quoted 6 lines
Quoted 2 lines
OK, look like avr32 should be a blocker here since at91 boards can do at-least. What is the plan on avr32, shall I look in to it?
I hope I can look for it in next couple of month. So v2016.11 should be doable, maybe v2017.01. Do you have some avr32 hardware to verify it?
Don't have.
thanks!
Signature · 1 line
Jagan.
PATCH v7 1/1 dm: at91: Add driver model support for the spi driver
Quoted 2 lines · Jagan Teki
On 19 August 2016 at 18:16, Andreas Bie?mann <[email protected]> wrote:
<snip>
Quoted 22 lines
Quoted 22 lines
Quoted 20 lines
Quoted 10 lines
non-dm code has to live for some time since this is a shared driver for
avr32 and arm architecture of atmel SoC. Unfortunately avr32 still lacks
dm
support in u-boot. I have some prepared patches but AFAIR there was a
problem with early malloc ... after that I had no time to get it done.Quoted 6 lines
Beside that I also insist on converting the remaining at91 boards to dm.
Since there are some boards I would suggest a time frame until end of
this
year.OK, look like avr32 should be a blocker here since at91 boards can do at-least. What is the plan on avr32, shall I look in to it?
Quoted 5 lines
Quoted 3 lines
I hope I can look for it in next couple of month. So v2016.11 should be
doable, maybe v2017.01. Do you have some avr32 hardware to verify it?Don't have.
It would be hard to verify it, if you would have taken that task ... So I'll do it, with a lower priority sometime next months.
Andreas
Quoted 2 lines
thanks!
PATCH v7 1/1 dm: at91: Add driver model support for the spi driver
Quoted 2 lines · Andreas Bie?mann
Quoted 1 line · Jagan Teki
<snip>
Quoted 3 lines
It would be hard to verify it, if you would have taken that task ... So I'll do it, with a lower priority sometime next months.
OK.
thanks!
Signature · 1 line
Jagan.
PATCH v7 1/1 dm: at91: Add driver model support for the spi driver
In reply to Jagan TekiHi Jagan,
Quoted 27 lines
-----Original Message-----
From: Jagan Teki [mailto:jagannadh.teki at gmail.com]
Sent: 2016?8?19? 19:36
To: Wenyou Yang - A41535 <[email protected]>
Cc: Wenyou Yang - A41535 <[email protected]>; u-
boot at lists.denx.de
Subject: Re: [U-Boot] [PATCH v7] dm: at91: Add driver model support for the spi driverQuoted 17 lines · On 8 August 2016 at 06:14, <[email protected]> wrote:
Hi Jagan,
Quoted 15 lines
-----Original Message-----
From: Jagan Teki [mailto:jagannadh.teki at gmail.com]
Sent: 2016?8?6? 21:00
To: Wenyou Yang <[email protected]>
Cc: U-Boot Mailing List <[email protected]>
Subject: Re: [U-Boot] [PATCH v7] dm: at91: Add driver model support for the spi driverQuoted 4 lines · Jagan Teki
Quoted 3 lines · Wenyou Yang
Add driver model support 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.
Need some info - how many boards still pending to use this driver to use it in
Quoted 8 lines
dm?
Quoted 3 lines
For now, only
sama5d2_xplainedhas used this drive in dm, other boards with AT91 SoC has not used dm driver, such as at91sam9g20ek, at91sam9x5ek,at91sam9m10g45ek, sama5d3xek. sama5d4ek, ....
Please convert these boards to dm as well, because driver still have non-dm code never know when it gets removed.
Okay, we will convert them.
Thank you for your reminder.
Quoted 4 lines
thanks!
--
Jagan.
Best Regards,
Wenyou Yang
PATCH v7 1/1 dm: at91: Add driver model support for the spi driver
In reply to Wenyou YangHi Wenyou,
Quoted 6 lines · Wenyou Yang
Add driver model support 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 <[email protected]>Reviewed-by Simon Glass <[email protected]>
This one breaks avr32 boards:
---8<---
02: dm: at91: Add driver model support for the spi driver
avr32: + atngw100 atngw100mkii
+../drivers/spi/atmel_spi.c:17:31: error: asm/arch/at91_spi.h: No such file or directory+../drivers/spi/atmel_spi.c:18:22: error: asm/gpio.h: No such file or directory
+make[2]: *** [drivers/spi/atmel_spi.o] Error 1
+make[1]: *** [drivers/spi] Error 2
+make: *** [sub-make] Error 2
--->8---
please fix this
Andreas
Quoted 369 lines
---
Changes in v7:
- Movegpio_request_list_by_name()to_probe(), remove*_ofdata_to_platdata().Changes in v6:
- Remove the two flash related options.Changes in v5:
- Changeclk_client.h->clk.hto adapt to clk API conversion.Changes in v4:
- Collect Reviewed-by tag.
- Update the clk API based on [PATCH] clk: convert API to match reset/mailbox fstyle (http://patchwork.ozlabs.org/patch/625342/).
- Remove check ondev_get_parent()return.
- Fixed the return value, -ENODEV->-EINVAL.
- Retain #include <asm/arch/clk.h> line.Changes in v3:
- Remove redundant log print.Changes in v2:
- Add clock support.drivers/spi/Kconfig | 7 ++ drivers/spi/atmel_spi.c | 295 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 302 insertions(+)drivers/spi/Kconfig +7
-0@@ -32,6 +32,13 @@ config ATH79_SPI uses driver model and requires a device tree binding to operate. please refer to doc/device-tree-bindings/spi/spi-ath79.txt. +config ATMEL_SPI + bool "Atmel SPI driver" + depends on ARCH_AT91 + help + Enable the Atmel SPI driver. This driver can be used to access + the SPI Flash, such as AT25DF321. + config CADENCE_QSPI bool "Cadence QSPI driver" helpdrivers/spi/atmel_spi.c +295
-0@@ -4,6 +4,9 @@* SPDX-License-Identifier: GPL-2.0+ */ #include <common.h> +#include <clk.h> +#include <dm.h> +#include <fdtdec.h> #include <spi.h> #include <malloc.h> @@ -11,9 +14,15 @@#include <asm/arch/clk.h> #include <asm/arch/hardware.h> +#include <asm/arch/at91_spi.h> +#include <asm/gpio.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;@@ -209,3 +218,289 @@ out:return 0 ; } + +#else + +#define MAX_CS_COUNT 4 + +struct atmel_spi_platdata { +struct at91_spi *regs; +}; + +struct atmel_spi_priv { +unsigned int freq;/* Default frequency */ +unsigned int mode; +ulong bus_clk_rate; +struct gpio_desc cs_gpios[MAX_CS_COUNT ]; +}; + +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; +u32 cs = slave_plat->cs; +u32 freq = priv->freq; +u32 scbr, csrx, mode; + + scbr = (priv->bus_clk_rate + freq -1 ) / freq; +if (scbr > ATMEL_SPI_CSRx_SCBR_MAX) +return -EINVAL ; + +if (scbr <1 ) + scbr =1 ; + + csrx =ATMEL_SPI_CSRx_SCBR (scbr); + csrx |=ATMEL_SPI_CSRx_BITS (ATMEL_SPI_BITS_8 ); + +if (!(priv->mode &SPI_CPHA )) + csrx |= ATMEL_SPI_CSRx_NCPHA; +if (priv->mode &SPI_CPOL ) + csrx |= ATMEL_SPI_CSRx_CPOL; + +writel (csrx, ®_base->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 (ATMEL_SPI_CR_SPIEN , ®_base->cr); + +return 0 ; +} + +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); + +writel (ATMEL_SPI_CR_SPIDIS , &bus_plat->regs->cr); + +return 0 ; +} + +static void atmel_spi_cs_activate (struct udevice *dev) +{ +struct udevice *bus =dev_get_parent (dev); +struct atmel_spi_priv *priv =dev_get_priv (bus); +struct dm_spi_slave_platdata *slave_plat =dev_get_parent_platdata (dev); +u32 cs = slave_plat->cs; + +dm_gpio_set_value (&priv->cs_gpios[cs],0 ); +} + +static void atmel_spi_cs_deactivate (struct udevice *dev) +{ +struct udevice *bus =dev_get_parent (dev); +struct atmel_spi_priv *priv =dev_get_priv (bus); +struct dm_spi_slave_platdata *slave_plat =dev_get_parent_platdata (dev); +u32 cs = slave_plat->cs; + +dm_gpio_set_value (&priv->cs_gpios[cs],1 ); +} + +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; + +u32 len_tx, len_rx, len; +u32 status; +const u8 *txp = dout; +u8 *rxp = din; +u8 value; + +if (bitlen ==0 ) + goto out; + +/* +* 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 ) { +atmel_spi_cs_activate (dev); + +/* +* 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! +*/ +readl (®_base->rdr); + } + +for (len_tx =0 , len_rx =0 ; len_rx < len; ) { + status =readl (®_base->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 ; +writel (value, ®_base->tdr); + len_tx++; + } + +if (status &ATMEL_SPI_SR_RDRF ) { + value =readl (®_base->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 =readl (®_base->sr); + }while (!(status &ATMEL_SPI_SR_TXEMPTY )); + +atmel_spi_cs_deactivate (dev); + } + +return 0 ; +} + +static int atmel_spi_set_speed (struct udevice *bus,uint speed) +{ +struct atmel_spi_priv *priv =dev_get_priv (bus); + + priv->freq = speed; + +return 0 ; +} + +static int atmel_spi_set_mode (struct udevice *bus,uint mode) +{ +struct atmel_spi_priv *priv =dev_get_priv (bus); + + priv->mode = mode; + +return 0 ; +} + +static const struct dm_spi_ops atmel_spi_ops = { + .claim_bus = atmel_spi_claim_bus, + .release_bus = atmel_spi_release_bus, + .xfer = atmel_spi_xfer, + .set_speed = atmel_spi_set_speed, + .set_mode = atmel_spi_set_mode, +/* +* cs_info is not needed, since we require all chip selects to be +* in the device tree explicitly +*/ +}; + +static int atmel_spi_enable_clk (struct udevice *bus) +{ +struct atmel_spi_priv *priv =dev_get_priv (bus); +struct udevice *dev_clk; +struct clk clk; +ulong clk_rate; +int periph; +int ret; + + ret =clk_get_by_index (bus,0 , &clk); +if (ret) +return -EINVAL ; + + periph =fdtdec_get_uint (gd->fdt_blob, clk.dev->of_offset,"reg" ,-1 ); +if (periph <0 ) +return -EINVAL ; + + dev_clk =dev_get_parent (clk.dev); + ret =clk_request (dev_clk, &clk); +if (ret) +return ret; + + clk.id = periph; + ret =clk_enable (&clk); +if (ret) +return ret; + + ret =clk_get_by_index (dev_clk,0 , &clk); +if (ret) +return ret; + + clk_rate =clk_get_rate (&clk); +if (!clk_rate) +return -EINVAL ; + + priv->bus_clk_rate = clk_rate; + +clk_free (&clk); + +return 0 ; +} + +static int atmel_spi_probe (struct udevice *bus) +{ +struct atmel_spi_platdata *bus_plat =dev_get_platdata (bus); +struct atmel_spi_priv *priv =dev_get_priv (bus); +int ret; + + ret =atmel_spi_enable_clk (bus); +if (ret) +return ret; + + bus_plat->regs = (struct at91_spi *)dev_get_addr (bus); + + ret =gpio_request_list_by_name (bus,"cs-gpios" , priv->cs_gpios, +ARRAY_SIZE (priv->cs_gpios),0 ); +if (ret <0 ) { +error ("Can't get %s gpios! Error: %d" , bus->name, ret); +return ret; + } + +writel (ATMEL_SPI_CR_SWRST , &bus_plat->regs->cr); + +return 0 ; +} + +static const struct udevice_id atmel_spi_ids[] = { + { .compatible ="atmel,at91rm9200-spi" }, + { } +}; + +U_BOOT_DRIVER (atmel_spi) = { + .name ="atmel_spi" , + .id =UCLASS_SPI , + .of_match = atmel_spi_ids, + .ops = &atmel_spi_ops, + .platdata_auto_alloc_size =sizeof (struct atmel_spi_platdata ), + .priv_auto_alloc_size =sizeof (struct atmel_spi_priv ), + .probe = atmel_spi_probe, +}; +#endif
PATCH v7 1/1 dm: at91: Add driver model support for the spi driver
Hi Andreas,
Quoted 27 lines
-----Original Message-----
From: Andreas Bie?mann [mailto:andreas at biessmann.org]
Sent: 2016?8?16? 5:15
To: Wenyou Yang <[email protected]>; U-Boot Mailing List <u- boot at lists.denx.de>
Cc: Simon Glass <[email protected]>; Jagan Teki <[email protected]>
Subject: Re: [PATCH v7] dm: at91: Add driver model support for the spi driverHi Wenyou,
Quoted 6 lines · Wenyou Yang
Add driver model support 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 <[email protected]>Reviewed-by Simon Glass <[email protected]>This one breaks avr32 boards:
---8<---
02: dm: at91: Add driver model support for the spi driveravr32: + atngw100 atngw100mkii
+../drivers/spi/atmel_spi.c:17:31: error:asm/arch/at91_spi.h: No such file or directory+../drivers/spi/atmel_spi.c:18:22: error:asm/gpio.h: No such file or directory
Review
Quoted 4 lines
(quoted diff) +3
-1+make[2]: *** [drivers/spi/atmel_spi.o] Error 1 +make[1]: *** [drivers/spi] Error 2 +make: *** [sub-make] Error 2 --->8---
It seems this error is not introduced by this patch.
Can we apply this patch first?
Quoted 354 lines
please fix this
Andreas
Quoted 349 lines
---
Changes in v7:
- Movegpio_request_list_by_name()to_probe(), remove*_ofdata_to_platdata().Changes in v6:
- Remove the two flash related options.Changes in v5:
- Changeclk_client.h->clk.hto adapt to clk API conversion.Changes in v4:
- Collect Reviewed-by tag.
- Update the clk API based on [PATCH] clk: convert API to match reset/mailbox fstyle (http://patchwork.ozlabs.org/patch/625342/).
- Remove check ondev_get_parent()return.
- Fixed the return value, -ENODEV->-EINVAL.
- Retain #include <asm/arch/clk.h> line.Changes in v3:
- Remove redundant log print.Changes in v2:
- Add clock support.drivers/spi/Kconfig | 7 ++ drivers/spi/atmel_spi.c | 295 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 302 insertions(+)drivers/spi/Kconfig index renamed from drivers/spi/Kconfig +0
-0aca385d..16ed231 100644
drivers/spi/Kconfig +7
-0@@ -32,6 +32,13 @@ config ATH79_SPI uses driver model and requires a device tree binding to operate. please refer to doc/device-tree-bindings/spi/spi-ath79.txt. +config ATMEL_SPI + bool "Atmel SPI driver" + depends on ARCH_AT91 + help + Enable the Atmel SPI driver. This driver can be used to access + the SPI Flash, such as AT25DF321. + config CADENCE_QSPI bool "Cadence QSPI driver" helpdrivers/spi/atmel_spi.c index renamed from drivers/spi/atmel_spi.c +0
-0ed6278b..db40631 100644
drivers/spi/atmel_spi.c +276
-0@@ -4,6 +4,9 @@* SPDX-License-Identifier: GPL-2.0+ */ #include <common.h> +#include <clk.h> +#include <dm.h> +#include <fdtdec.h> #include <spi.h> #include <malloc.h> @@ -11,9 +14,15 @@#include <asm/arch/clk.h> #include <asm/arch/hardware.h> +#include <asm/arch/at91_spi.h> +#include <asm/gpio.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;@@ -209,3 +218,289 @@ out:return 0 ; } + +#else + +#define MAX_CS_COUNT 4 + +struct atmel_spi_platdata { +struct at91_spi *regs; +}; + +struct atmel_spi_priv { +unsigned int freq;/* Default frequency */ +unsigned int mode; +ulong bus_clk_rate; +struct gpio_desc cs_gpios[MAX_CS_COUNT ]; }; + +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; +u32 cs = slave_plat->cs; +u32 freq = priv->freq; +u32 scbr, csrx, mode; + + scbr = (priv->bus_clk_rate + freq -1 ) / freq; +if (scbr > ATMEL_SPI_CSRx_SCBR_MAX) +return -EINVAL ; + +if (scbr <1 ) + scbr =1 ; + + csrx =ATMEL_SPI_CSRx_SCBR (scbr); + csrx |=ATMEL_SPI_CSRx_BITS (ATMEL_SPI_BITS_8 ); + +if (!(priv->mode &SPI_CPHA )) + csrx |= ATMEL_SPI_CSRx_NCPHA; +if (priv->mode &SPI_CPOL ) + csrx |= ATMEL_SPI_CSRx_CPOL; + +writel (csrx, ®_base->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 (ATMEL_SPI_CR_SPIEN , ®_base->cr); + +return 0 ; +} + +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); + +writel (ATMEL_SPI_CR_SPIDIS , &bus_plat->regs->cr); + +return 0 ; +} + +static void atmel_spi_cs_activate (struct udevice *dev) { +struct udevice *bus =dev_get_parent (dev); +struct atmel_spi_priv *priv =dev_get_priv (bus); +struct dm_spi_slave_platdata *slave_plat =dev_get_parent_platdata (dev); +u32 cs = slave_plat->cs; + +dm_gpio_set_value (&priv->cs_gpios[cs],0 ); } + +static void atmel_spi_cs_deactivate (struct udevice *dev) { +struct udevice *bus =dev_get_parent (dev); +struct atmel_spi_priv *priv =dev_get_priv (bus); +struct dm_spi_slave_platdata *slave_plat =dev_get_parent_platdata (dev); +u32 cs = slave_plat->cs; + +dm_gpio_set_value (&priv->cs_gpios[cs],1 ); } + +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; + +u32 len_tx, len_rx, len; +u32 status; +const u8 *txp = dout; +u8 *rxp = din; +u8 value; + +if (bitlen ==0 ) + goto out; + +/* +* 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 ) { +atmel_spi_cs_activate (dev); + +/* +* 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! +*/ +readl (®_base->rdr); + } + +for (len_tx =0 , len_rx =0 ; len_rx < len; ) { + status =readl (®_base->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 ; +writel (value, ®_base->tdr); + len_tx++; + } + +if (status &ATMEL_SPI_SR_RDRF ) { + value =readl (®_base->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 =readl (®_base->sr); + }while (!(status &ATMEL_SPI_SR_TXEMPTY )); + +atmel_spi_cs_deactivate (dev); + } + +return 0 ; +} + +static int atmel_spi_set_speed (struct udevice *bus,uint speed) { +struct atmel_spi_priv *priv =dev_get_priv (bus); + + priv->freq = speed; + +return 0 ; +} + +static int atmel_spi_set_mode (struct udevice *bus,uint mode) { +struct atmel_spi_priv *priv =dev_get_priv (bus); + + priv->mode = mode; + +return 0 ; +} + +static const struct dm_spi_ops atmel_spi_ops = { + .claim_bus = atmel_spi_claim_bus, + .release_bus = atmel_spi_release_bus, + .xfer = atmel_spi_xfer, + .set_speed = atmel_spi_set_speed, + .set_mode = atmel_spi_set_mode, +/* +* cs_info is not needed, since we require all chip selects to be +* in the device tree explicitly +*/ +}; + +static int atmel_spi_enable_clk (struct udevice *bus) { +struct atmel_spi_priv *priv =dev_get_priv (bus); +struct udevice *dev_clk; +struct clk clk; +ulong clk_rate; +int periph; +int ret; + + ret =clk_get_by_index (bus,0 , &clk); +if (ret) +return -EINVAL ; + + periph =fdtdec_get_uint (gd->fdt_blob, clk.dev->of_offset,"reg" ,-1 ); +if (periph <0 ) +return -EINVAL ; + + dev_clk =dev_get_parent (clk.dev); + ret =clk_request (dev_clk, &clk); +if (ret) +return ret; + + clk.id = periph; + ret =clk_enable (&clk); +if (ret) +return ret; + + ret =clk_get_by_index (dev_clk,0 , &clk); +if (ret) +return ret; + + clk_rate =clk_get_rate (&clk); +if (!clk_rate) +return -EINVAL ; + + priv->bus_clk_rate = clk_rate; + +clk_free (&clk); + +return 0 ; +} + +static int atmel_spi_probe (struct udevice *bus) { +struct atmel_spi_platdata *bus_plat =dev_get_platdata (bus); +struct atmel_spi_priv *priv =dev_get_priv (bus); +int ret; + + ret =atmel_spi_enable_clk (bus); +if (ret) +return ret; + + bus_plat->regs = (struct at91_spi *)dev_get_addr (bus); + + ret =gpio_request_list_by_name (bus,"cs-gpios" , priv->cs_gpios, +ARRAY_SIZE (priv->cs_gpios),0 ); +if (ret <0 ) { +error ("Can't get %s gpios! Error: %d" , bus->name, ret); +return ret; + } + +writel (ATMEL_SPI_CR_SWRST , &bus_plat->regs->cr); + +return 0 ; +} + +static const struct udevice_id atmel_spi_ids[] = { + { .compatible ="atmel,at91rm9200-spi" }, + { } +}; + +U_BOOT_DRIVER (atmel_spi) = { + .name ="atmel_spi" , + .id = UCLASS_SPI,
Quoted 8 lines
drivers/spi/atmel_spi.c out: · line 506
Quoted 8 lines
drivers/spi/atmel_spi.c +7
-0+ .of_match = atmel_spi_ids, + .ops = &atmel_spi_ops, + .platdata_auto_alloc_size = sizeof(struct atmel_spi_platdata), + .priv_auto_alloc_size = sizeof(struct atmel_spi_priv), + .probe = atmel_spi_probe, +}; +#endif
Best Regards,
Wenyou Yang
PATCH v7 1/1 dm: at91: Add driver model support for the spi driver
Hi Wenyou,
Quoted 23 lines · Wenyou.Yang at microchip.com
Hi Andreas,
Quoted 21 lines
-----Original Message-----
From: Andreas Bie?mann [mailto:andreas at biessmann.org]
Sent: 2016?8?16? 5:15
To: Wenyou Yang <[email protected]>; U-Boot Mailing List <u- boot at lists.denx.de>
Cc: Simon Glass <[email protected]>; Jagan Teki <[email protected]>
Subject: Re: [PATCH v7] dm: at91: Add driver model support for the spi driverHi Wenyou,
Quoted 6 lines · Wenyou Yang
Add driver model support 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 <[email protected]>Reviewed-by Simon Glass <[email protected]>This one breaks avr32 boards:
Quoted 13 lines
Review
Quoted 11 lines
---8<---
02: dm: at91: Add driver model support for the spi driveravr32: + atngw100 atngw100mkii
+../drivers/spi/atmel_spi.c:17:31: error:asm/arch/at91_spi.h: No such file or directory+../drivers/spi/atmel_spi.c:18:22: error:asm/gpio.h: No such file or directory(quoted diff) +3
-1+make[2]: *** [drivers/spi/atmel_spi.o] Error 1 +make[1]: *** [drivers/spi] Error 2 +make: *** [sub-make] Error 2 --->8---It seems this error is not introduced by this patch.
Well, I think it is introduced by this patch. This patch chenges the atmel_cpi driver in such a way that it breaks for avr32 architecture which has a slight different structure in files.
Quoted 1 line
Can we apply this patch first?
No, not if it breaks AVR32.
Andreas
Quoted 367 lines
Quoted 355 lines
please fix this
Andreas
Quoted 349 lines
---
Changes in v7:
- Movegpio_request_list_by_name()to_probe(), remove*_ofdata_to_platdata().Changes in v6:
- Remove the two flash related options.Changes in v5:
- Changeclk_client.h->clk.hto adapt to clk API conversion.Changes in v4:
- Collect Reviewed-by tag.
- Update the clk API based on [PATCH] clk: convert API to match reset/mailbox fstyle (http://patchwork.ozlabs.org/patch/625342/).
- Remove check ondev_get_parent()return.
- Fixed the return value, -ENODEV->-EINVAL.
- Retain #include <asm/arch/clk.h> line.Changes in v3:
- Remove redundant log print.Changes in v2:
- Add clock support.drivers/spi/Kconfig | 7 ++ drivers/spi/atmel_spi.c | 295 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 302 insertions(+)drivers/spi/Kconfig index renamed from drivers/spi/Kconfig +0
-0aca385d..16ed231 100644
drivers/spi/Kconfig +7
-0@@ -32,6 +32,13 @@ config ATH79_SPI uses driver model and requires a device tree binding to operate. please refer to doc/device-tree-bindings/spi/spi-ath79.txt. +config ATMEL_SPI + bool "Atmel SPI driver" + depends on ARCH_AT91 + help + Enable the Atmel SPI driver. This driver can be used to access + the SPI Flash, such as AT25DF321. + config CADENCE_QSPI bool "Cadence QSPI driver" helpdrivers/spi/atmel_spi.c index renamed from drivers/spi/atmel_spi.c +0
-0ed6278b..db40631 100644
drivers/spi/atmel_spi.c +276
-0@@ -4,6 +4,9 @@* SPDX-License-Identifier: GPL-2.0+ */ #include <common.h> +#include <clk.h> +#include <dm.h> +#include <fdtdec.h> #include <spi.h> #include <malloc.h> @@ -11,9 +14,15 @@#include <asm/arch/clk.h> #include <asm/arch/hardware.h> +#include <asm/arch/at91_spi.h> +#include <asm/gpio.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;@@ -209,3 +218,289 @@ out:return 0 ; } + +#else + +#define MAX_CS_COUNT 4 + +struct atmel_spi_platdata { +struct at91_spi *regs; +}; + +struct atmel_spi_priv { +unsigned int freq;/* Default frequency */ +unsigned int mode; +ulong bus_clk_rate; +struct gpio_desc cs_gpios[MAX_CS_COUNT ]; }; + +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; +u32 cs = slave_plat->cs; +u32 freq = priv->freq; +u32 scbr, csrx, mode; + + scbr = (priv->bus_clk_rate + freq -1 ) / freq; +if (scbr > ATMEL_SPI_CSRx_SCBR_MAX) +return -EINVAL ; + +if (scbr <1 ) + scbr =1 ; + + csrx =ATMEL_SPI_CSRx_SCBR (scbr); + csrx |=ATMEL_SPI_CSRx_BITS (ATMEL_SPI_BITS_8 ); + +if (!(priv->mode &SPI_CPHA )) + csrx |= ATMEL_SPI_CSRx_NCPHA; +if (priv->mode &SPI_CPOL ) + csrx |= ATMEL_SPI_CSRx_CPOL; + +writel (csrx, ®_base->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 (ATMEL_SPI_CR_SPIEN , ®_base->cr); + +return 0 ; +} + +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); + +writel (ATMEL_SPI_CR_SPIDIS , &bus_plat->regs->cr); + +return 0 ; +} + +static void atmel_spi_cs_activate (struct udevice *dev) { +struct udevice *bus =dev_get_parent (dev); +struct atmel_spi_priv *priv =dev_get_priv (bus); +struct dm_spi_slave_platdata *slave_plat =dev_get_parent_platdata (dev); +u32 cs = slave_plat->cs; + +dm_gpio_set_value (&priv->cs_gpios[cs],0 ); } + +static void atmel_spi_cs_deactivate (struct udevice *dev) { +struct udevice *bus =dev_get_parent (dev); +struct atmel_spi_priv *priv =dev_get_priv (bus); +struct dm_spi_slave_platdata *slave_plat =dev_get_parent_platdata (dev); +u32 cs = slave_plat->cs; + +dm_gpio_set_value (&priv->cs_gpios[cs],1 ); } + +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; + +u32 len_tx, len_rx, len; +u32 status; +const u8 *txp = dout; +u8 *rxp = din; +u8 value; + +if (bitlen ==0 ) + goto out; + +/* +* 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 ) { +atmel_spi_cs_activate (dev); + +/* +* 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! +*/ +readl (®_base->rdr); + } + +for (len_tx =0 , len_rx =0 ; len_rx < len; ) { + status =readl (®_base->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 ; +writel (value, ®_base->tdr); + len_tx++; + } + +if (status &ATMEL_SPI_SR_RDRF ) { + value =readl (®_base->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 =readl (®_base->sr); + }while (!(status &ATMEL_SPI_SR_TXEMPTY )); + +atmel_spi_cs_deactivate (dev); + } + +return 0 ; +} + +static int atmel_spi_set_speed (struct udevice *bus,uint speed) { +struct atmel_spi_priv *priv =dev_get_priv (bus); + + priv->freq = speed; + +return 0 ; +} + +static int atmel_spi_set_mode (struct udevice *bus,uint mode) { +struct atmel_spi_priv *priv =dev_get_priv (bus); + + priv->mode = mode; + +return 0 ; +} + +static const struct dm_spi_ops atmel_spi_ops = { + .claim_bus = atmel_spi_claim_bus, + .release_bus = atmel_spi_release_bus, + .xfer = atmel_spi_xfer, + .set_speed = atmel_spi_set_speed, + .set_mode = atmel_spi_set_mode, +/* +* cs_info is not needed, since we require all chip selects to be +* in the device tree explicitly +*/ +}; + +static int atmel_spi_enable_clk (struct udevice *bus) { +struct atmel_spi_priv *priv =dev_get_priv (bus); +struct udevice *dev_clk; +struct clk clk; +ulong clk_rate; +int periph; +int ret; + + ret =clk_get_by_index (bus,0 , &clk); +if (ret) +return -EINVAL ; + + periph =fdtdec_get_uint (gd->fdt_blob, clk.dev->of_offset,"reg" ,-1 ); +if (periph <0 ) +return -EINVAL ; + + dev_clk =dev_get_parent (clk.dev); + ret =clk_request (dev_clk, &clk); +if (ret) +return ret; + + clk.id = periph; + ret =clk_enable (&clk); +if (ret) +return ret; + + ret =clk_get_by_index (dev_clk,0 , &clk); +if (ret) +return ret; + + clk_rate =clk_get_rate (&clk); +if (!clk_rate) +return -EINVAL ; + + priv->bus_clk_rate = clk_rate; + +clk_free (&clk); + +return 0 ; +} + +static int atmel_spi_probe (struct udevice *bus) { +struct atmel_spi_platdata *bus_plat =dev_get_platdata (bus); +struct atmel_spi_priv *priv =dev_get_priv (bus); +int ret; + + ret =atmel_spi_enable_clk (bus); +if (ret) +return ret; + + bus_plat->regs = (struct at91_spi *)dev_get_addr (bus); + + ret =gpio_request_list_by_name (bus,"cs-gpios" , priv->cs_gpios, +ARRAY_SIZE (priv->cs_gpios),0 ); +if (ret <0 ) { +error ("Can't get %s gpios! Error: %d" , bus->name, ret); +return ret; + } + +writel (ATMEL_SPI_CR_SWRST , &bus_plat->regs->cr); + +return 0 ; +} + +static const struct udevice_id atmel_spi_ids[] = { + { .compatible ="atmel,at91rm9200-spi" }, + { } +}; + +U_BOOT_DRIVER (atmel_spi) = { + .name ="atmel_spi" , + .id = UCLASS_SPI,Quoted 8 lines
drivers/spi/atmel_spi.c out: · line 506
Quoted 8 lines
drivers/spi/atmel_spi.c +7
-0+ .of_match = atmel_spi_ids, + .ops = &atmel_spi_ops, + .platdata_auto_alloc_size = sizeof(struct atmel_spi_platdata), + .priv_auto_alloc_size = sizeof(struct atmel_spi_priv), + .probe = atmel_spi_probe, +}; +#endif Best Regards,
Wenyou Yang