[U-Boot] [PATCH v3 8/9] spi: davinci: add support for multiple bus and chip select
Karicheri, Muralidharan
m-karicheri2 at ti.com
Wed Mar 26 20:49:49 CET 2014
>-----Original Message-----
>From: Jagan Teki [mailto:jagannadh.teki at gmail.com]
>Sent: Sunday, March 23, 2014 7:07 AM
>To: Karicheri, Muralidharan
>Cc: Rini, Tom; u-boot at lists.denx.de; Chang, Rex
>Subject: Re: [U-Boot] [PATCH v3 8/9] spi: davinci: add support for multiple bus and chip
>select
>
>Hi,
>
>On Sat, Mar 22, 2014 at 2:21 AM, Murali Karicheri <m-karicheri2 at ti.com> wrote:
>> Currently davinci spi driver supports only bus 0 cs 0.
>> This patch allows driver to support bus 1 and bus 2 with configurable
>> number of chip selects. Also defaults are selected in a way to avoid
>> regression on other platforms that uses davinci spi driver and has
>> only one spi bus.
>>
>> Signed-off-by: Rex Chang <rchang at ti.com>
>> Signed-off-by: Murali Karicheri <m-karicheri2 at ti.com>
>> Acked-by: Tom Rini <trini at ti.com>
>> ---
>> drivers/spi/davinci_spi.c | 60
>++++++++++++++++++++++++++++++++++++++++++---
>> drivers/spi/davinci_spi.h | 33 +++++++++++++++++++++++++
>> 2 files changed, 90 insertions(+), 3 deletions(-)
>>
>> diff --git a/drivers/spi/davinci_spi.c b/drivers/spi/davinci_spi.c
>> index e3fb321..b682bc4 100644
>> --- a/drivers/spi/davinci_spi.c
>> +++ b/drivers/spi/davinci_spi.c
>> @@ -32,7 +32,27 @@ struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int
>cs,
>> if (!ds)
>> return NULL;
>>
>> - ds->regs = (struct davinci_spi_regs *)CONFIG_SYS_SPI_BASE;
>> + ds->slave.bus = bus;
>> + ds->slave.cs = cs;
>> +
>> + switch (bus) {
>> + case SPI0_BUS:
>> + ds->regs = (struct davinci_spi_regs *)SPI0_BASE;
>> + break;
>> +#ifdef CONFIG_SYS_SPI1
>> + case SPI1_BUS:
>> + ds->regs = (struct davinci_spi_regs *)SPI0_BASE;
>> + break;
>> +#endif
>> +#ifdef CONFIG_SYS_SPI2
>> + case SPI2_BUS:
>> + ds->regs = (struct davinci_spi_regs *)SPI2_BASE;
>> + break;
>> +#endif
>> + default: /* Invalid bus number */
>> + return NULL;
>> + }
>> +
>> ds->freq = max_hz;
>>
>> return &ds->slave;
>> @@ -59,7 +79,7 @@ int spi_claim_bus(struct spi_slave *slave)
>> writel(SPIGCR1_MASTER_MASK | SPIGCR1_CLKMOD_MASK,
>> &ds->regs->gcr1);
>>
>> /* CS, CLK, SIMO and SOMI are functional pins */
>> - writel((SPIPC0_EN0FUN_MASK | SPIPC0_CLKFUN_MASK |
>> + writel(((1 << slave->cs) | SPIPC0_CLKFUN_MASK |
>> SPIPC0_DOFUN_MASK | SPIPC0_DIFUN_MASK),
>> &ds->regs->pc0);
>>
>> /* setup format */
>> @@ -262,9 +282,43 @@ out:
>> return 0;
>> }
>>
>> +#ifdef CONFIG_SYS_SPI1
>> +static int bus1_cs_valid(unsigned int bus, unsigned int cs) {
>> + if ((bus == SPI1_BUS) && (cs < SPI1_NUM_CS))
>> + return 1;
>> + return 0;
>> +}
>> +#else
>> +static int bus1_cs_valid(unsigned int bus, unsigned int cs) {
>> + return 0;
>> +}
>> +#endif
>> +
>> +#ifdef CONFIG_SYS_SPI2
>> +static int bus2_cs_valid(unsigned int bus, unsigned int cs) {
>> + if ((bus == SPI2_BUS) && (cs < SPI2_NUM_CS))
>> + return 1;
>> + return 0;
>> +}
>> +#else
>> +static int bus2_cs_valid(unsigned int bus, unsigned int cs) {
>> + return 0;
>> +}
>> +#endif
>> +
>> int spi_cs_is_valid(unsigned int bus, unsigned int cs) {
>> - return bus == 0 && cs == 0;
>> + if ((bus == SPI0_BUS) && (cs < SPI0_NUM_CS))
>> + return 1;
>> + else if (bus1_cs_valid(bus, cs))
>> + return 1;
>> + else if (bus2_cs_valid(bus, cs))
>> + return 1;
>> + return 0;
>> }
>>
>> void spi_cs_activate(struct spi_slave *slave) diff --git
>> a/drivers/spi/davinci_spi.h b/drivers/spi/davinci_spi.h index
>> 33f69b5..d4612d3 100644
>> --- a/drivers/spi/davinci_spi.h
>> +++ b/drivers/spi/davinci_spi.h
>> @@ -74,6 +74,39 @@ struct davinci_spi_regs {
>> /* SPIDEF */
>> #define SPIDEF_CSDEF0_MASK BIT(0)
>>
>> +#define SPI0_BUS 0
>> +#define SPI0_BASE CONFIG_SYS_SPI_BASE
>> +/*
>> + * Define default SPI0_NUM_CS as 1 for existing platforms that uses
>> +this
>> + * driver. Platform can configure number of CS using
>> +CONFIG_SYS_SPI0_NUM_CS
>> + * if more than one CS is supported and by defining CONFIG_SYS_SPI0.
>> + */
>> +#ifndef CONFIG_SYS_SPI0
>> +#define SPI0_NUM_CS 1
>> +#else
>> +#define SPI0_NUM_CS CONFIG_SYS_SPI0_NUM_CS
>> +#endif
>> +
>> +/*
>> + * define CONFIG_SYS_SPI1 when platform has spi-1 device (bus #1) and
>> + * CONFIG_SYS_SPI1_NUM_CS defines number of CS on this bus */ #ifdef
>> +CONFIG_SYS_SPI1
>> +#define SPI1_BUS 1
>> +#define SPI1_NUM_CS CONFIG_SYS_SPI1_NUM_CS
>> +#define SPI1_BASE CONFIG_SYS_SPI1_BASE
>> +#endif
>> +
>> +/*
>> + * define CONFIG_SYS_SPI2 when platform has spi-2 device (bus #2) and
>> + * CONFIG_SYS_SPI2_NUM_CS defines number of CS on this bus */ #ifdef
>> +CONFIG_SYS_SPI2
>> +#define SPI2_BUS 2
>> +#define SPI2_NUM_CS CONFIG_SYS_SPI2_NUM_CS
>> +#define SPI2_BASE CONFIG_SYS_SPI2_BASE
>> +#endif
>> +
>> struct davinci_spi_slave {
>> struct spi_slave slave;
>> struct davinci_spi_regs *regs;
>> --
>> 1.7.9.5
>
>This code looks more static, can you try get the bus and cs from sf probe and according
>assign the reg_base.
>
>fyi: look at drivers/spi/zynq_spi.c where based on the bus number we assign the reg_base
>and prior to that we can do the same for bus and cs.
>
Jagan,
Thanks for your comments.
I looked at the driver code. In the example driver you provided
the reg_base is chosen based on device number and the hardware.h
define the base0 and base1 address and assign it based on device
number. davinci_spi is re-used on many devices. All of the
DaVinci devices such as dm644x, dm355, dm365 etc that mostly has
one SPI device vs keystone devices such k2h/k that has 3 devices.
If I follow this approach, I need to define BASE1 and BASE2
in the hardware.h of all devices that this software must run.
This is not right since DaVinci devices has only one SPI device
I think this is what best we can do given that the driver needs to be
re-used across multiple devices and static is the way to go unless
you have better suggestion to handle this scenario.
Thanks.
Murali
>Let me know for any more info.
>
>thanks!
>--
>Jagan.
More information about the U-Boot
mailing list