Commit 78f47b7353ebe1f243203dcc1ce0a2a374c08a40

Authored by Allen Martin
Committed by Tom Warren
1 parent 6b3a03e112

spi: add common fdt SPI driver interface

Add a common interface to fdt based SPI drivers.  Each driver is
represented by a table entry in fdt_spi_drivers[].  If there are
multiple SPI drivers in the table, the first driver to return success
from spi_init() will be registered as the SPI driver.

Signed-off-by: Allen Martin <amartin@nvidia.com>
Signed-off-by: Tom Warren <twarren@nvidia.com>
Reviewed-by: Stephen Warren <swarren@nvidia.com>

Showing 8 changed files with 224 additions and 46 deletions Side-by-side Diff

arch/arm/include/asm/arch-tegra20/tegra20_sflash.h
... ... @@ -27,5 +27,16 @@
27 27  
28 28 #include <asm/types.h>
29 29  
  30 +int tegra20_spi_cs_is_valid(unsigned int bus, unsigned int cs);
  31 +struct spi_slave *tegra20_spi_setup_slave(unsigned int bus, unsigned int cs,
  32 + unsigned int max_hz, unsigned int mode);
  33 +void tegra20_spi_free_slave(struct spi_slave *slave);
  34 +int tegra20_spi_init(int *node_list, int count);
  35 +int tegra20_spi_claim_bus(struct spi_slave *slave);
  36 +void tegra20_spi_cs_activate(struct spi_slave *slave);
  37 +void tegra20_spi_cs_deactivate(struct spi_slave *slave);
  38 +int tegra20_spi_xfer(struct spi_slave *slave, unsigned int bitlen,
  39 + const void *data_out, void *data_in, unsigned long flags);
  40 +
30 41 #endif /* _TEGRA20_SPI_H_ */
arch/arm/include/asm/arch-tegra20/tegra20_slink.h
... ... @@ -27,5 +27,16 @@
27 27  
28 28 #include <asm/types.h>
29 29  
  30 +int tegra30_spi_init(int *node_list, int count);
  31 +int tegra30_spi_cs_is_valid(unsigned int bus, unsigned int cs);
  32 +struct spi_slave *tegra30_spi_setup_slave(unsigned int bus, unsigned int cs,
  33 + unsigned int max_hz, unsigned int mode);
  34 +void tegra30_spi_free_slave(struct spi_slave *slave);
  35 +int tegra30_spi_claim_bus(struct spi_slave *slave);
  36 +void tegra30_spi_cs_activate(struct spi_slave *slave);
  37 +void tegra30_spi_cs_deactivate(struct spi_slave *slave);
  38 +int tegra30_spi_xfer(struct spi_slave *slave, unsigned int bitlen,
  39 + const void *data_out, void *data_in, unsigned long flags);
  40 +
30 41 #endif /* _TEGRA30_SPI_H_ */
board/nvidia/common/board.c
... ... @@ -132,7 +132,7 @@
132 132 clock_init();
133 133 clock_verify();
134 134  
135   -#if defined(CONFIG_TEGRA20_SFLASH) || defined(CONFIG_TEGRA20_SLINK)
  135 +#ifdef CONFIG_FDT_SPI
136 136 pin_mux_spi();
137 137 spi_init();
138 138 #endif
drivers/spi/Makefile
... ... @@ -46,6 +46,7 @@
46 46 COBJS-$(CONFIG_SOFT_SPI) += soft_spi.o
47 47 COBJS-$(CONFIG_SH_SPI) += sh_spi.o
48 48 COBJS-$(CONFIG_FSL_ESPI) += fsl_espi.o
  49 +COBJS-$(CONFIG_FDT_SPI) += fdt_spi.o
49 50 COBJS-$(CONFIG_TEGRA20_SFLASH) += tegra20_sflash.o
50 51 COBJS-$(CONFIG_TEGRA20_SLINK) += tegra20_slink.o
51 52 COBJS-$(CONFIG_XILINX_SPI) += xilinx_spi.o
drivers/spi/fdt_spi.c
  1 +/*
  2 + * Common fdt based SPI driver front end
  3 + *
  4 + * Copyright (c) 2013 NVIDIA Corporation
  5 + *
  6 + * See file CREDITS for list of people who contributed to this
  7 + * project.
  8 + *
  9 + * This software is licensed under the terms of the GNU General Public
  10 + * License version 2, as published by the Free Software Foundation, and
  11 + * may be copied, distributed, and modified under those terms.
  12 + *
  13 + * This program is distributed in the hope that it will be useful,
  14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16 + * GNU General Public License for more details.
  17 + *
  18 + * You should have received a copy of the GNU General Public License
  19 + * along with this program; if not, write to the Free Software
  20 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  21 + * MA 02111-1307 USA
  22 + */
  23 +
  24 +#include <common.h>
  25 +#include <malloc.h>
  26 +#include <asm/io.h>
  27 +#include <asm/gpio.h>
  28 +#include <asm/arch/clock.h>
  29 +#include <asm/arch-tegra/clk_rst.h>
  30 +#include <asm/arch-tegra20/tegra20_sflash.h>
  31 +#include <asm/arch-tegra20/tegra20_slink.h>
  32 +#include <spi.h>
  33 +#include <fdtdec.h>
  34 +
  35 +DECLARE_GLOBAL_DATA_PTR;
  36 +
  37 +struct fdt_spi_driver {
  38 + int compat;
  39 + int max_ctrls;
  40 + int (*init)(int *node_list, int count);
  41 + int (*claim_bus)(struct spi_slave *slave);
  42 + int (*release_bus)(struct spi_slave *slave);
  43 + int (*cs_is_valid)(unsigned int bus, unsigned int cs);
  44 + struct spi_slave *(*setup_slave)(unsigned int bus, unsigned int cs,
  45 + unsigned int max_hz, unsigned int mode);
  46 + void (*free_slave)(struct spi_slave *slave);
  47 + void (*cs_activate)(struct spi_slave *slave);
  48 + void (*cs_deactivate)(struct spi_slave *slave);
  49 + int (*xfer)(struct spi_slave *slave, unsigned int bitlen,
  50 + const void *data_out, void *data_in, unsigned long flags);
  51 +};
  52 +
  53 +static struct fdt_spi_driver fdt_spi_drivers[] = {
  54 +#ifdef CONFIG_TEGRA20_SFLASH
  55 + {
  56 + .compat = COMPAT_NVIDIA_TEGRA20_SFLASH,
  57 + .max_ctrls = 1,
  58 + .init = tegra20_spi_init,
  59 + .claim_bus = tegra20_spi_claim_bus,
  60 + .cs_is_valid = tegra20_spi_cs_is_valid,
  61 + .setup_slave = tegra20_spi_setup_slave,
  62 + .free_slave = tegra20_spi_free_slave,
  63 + .cs_activate = tegra20_spi_cs_activate,
  64 + .cs_deactivate = tegra20_spi_cs_deactivate,
  65 + .xfer = tegra20_spi_xfer,
  66 + },
  67 +#endif
  68 +#ifdef CONFIG_TEGRA20_SLINK
  69 + {
  70 + .compat = COMPAT_NVIDIA_TEGRA20_SLINK,
  71 + .max_ctrls = CONFIG_TEGRA_SLINK_CTRLS,
  72 + .init = tegra30_spi_init,
  73 + .claim_bus = tegra30_spi_claim_bus,
  74 + .cs_is_valid = tegra30_spi_cs_is_valid,
  75 + .setup_slave = tegra30_spi_setup_slave,
  76 + .free_slave = tegra30_spi_free_slave,
  77 + .cs_activate = tegra30_spi_cs_activate,
  78 + .cs_deactivate = tegra30_spi_cs_deactivate,
  79 + .xfer = tegra30_spi_xfer,
  80 + },
  81 +#endif
  82 +};
  83 +
  84 +static struct fdt_spi_driver *driver;
  85 +
  86 +int spi_cs_is_valid(unsigned int bus, unsigned int cs)
  87 +{
  88 + if (!driver)
  89 + return 0;
  90 + else if (!driver->cs_is_valid)
  91 + return 1;
  92 + else
  93 + return driver->cs_is_valid(bus, cs);
  94 +}
  95 +
  96 +struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
  97 + unsigned int max_hz, unsigned int mode)
  98 +{
  99 + if (!driver || !driver->setup_slave)
  100 + return NULL;
  101 +
  102 + return driver->setup_slave(bus, cs, max_hz, mode);
  103 +}
  104 +
  105 +void spi_free_slave(struct spi_slave *slave)
  106 +{
  107 + if (driver && driver->free_slave)
  108 + return driver->free_slave(slave);
  109 +}
  110 +
  111 +static int spi_init_driver(struct fdt_spi_driver *driver)
  112 +{
  113 + int count;
  114 + int node_list[driver->max_ctrls];
  115 +
  116 + count = fdtdec_find_aliases_for_id(gd->fdt_blob, "spi",
  117 + driver->compat,
  118 + node_list,
  119 + driver->max_ctrls);
  120 + return driver->init(node_list, count);
  121 +}
  122 +
  123 +void spi_init(void)
  124 +{
  125 + int i;
  126 +
  127 + for (i = 0; i < ARRAY_SIZE(fdt_spi_drivers); i++) {
  128 + driver = &fdt_spi_drivers[i];
  129 + if (!spi_init_driver(driver))
  130 + break;
  131 + }
  132 + if (i == ARRAY_SIZE(fdt_spi_drivers))
  133 + driver = NULL;
  134 +}
  135 +
  136 +int spi_claim_bus(struct spi_slave *slave)
  137 +{
  138 + if (!driver)
  139 + return 1;
  140 + if (!driver->claim_bus)
  141 + return 0;
  142 +
  143 + return driver->claim_bus(slave);
  144 +}
  145 +
  146 +void spi_release_bus(struct spi_slave *slave)
  147 +{
  148 + if (driver && driver->release_bus)
  149 + driver->release_bus(slave);
  150 +}
  151 +
  152 +void spi_cs_activate(struct spi_slave *slave)
  153 +{
  154 + if (driver && driver->cs_activate)
  155 + driver->cs_activate(slave);
  156 +}
  157 +
  158 +void spi_cs_deactivate(struct spi_slave *slave)
  159 +{
  160 + if (driver && driver->cs_deactivate)
  161 + driver->cs_deactivate(slave);
  162 +}
  163 +
  164 +int spi_xfer(struct spi_slave *slave, unsigned int bitlen,
  165 + const void *data_out, void *data_in, unsigned long flags)
  166 +{
  167 + if (!driver || !driver->xfer)
  168 + return -1;
  169 +
  170 + return driver->xfer(slave, bitlen, data_out, data_in, flags);
  171 +}
drivers/spi/tegra20_sflash.c
... ... @@ -101,7 +101,7 @@
101 101 return container_of(slave, struct tegra_spi_slave, slave);
102 102 }
103 103  
104   -int spi_cs_is_valid(unsigned int bus, unsigned int cs)
  104 +int tegra20_spi_cs_is_valid(unsigned int bus, unsigned int cs)
105 105 {
106 106 /* Tegra20 SPI-Flash - only 1 device ('bus/cs') */
107 107 if (bus != 0 || cs != 0)
... ... @@ -110,8 +110,8 @@
110 110 return 1;
111 111 }
112 112  
113   -struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
114   - unsigned int max_hz, unsigned int mode)
  113 +struct spi_slave *tegra20_spi_setup_slave(unsigned int bus, unsigned int cs,
  114 + unsigned int max_hz, unsigned int mode)
115 115 {
116 116 struct tegra_spi_slave *spi;
117 117  
118 118  
119 119  
120 120  
... ... @@ -151,25 +151,20 @@
151 151 return &spi->slave;
152 152 }
153 153  
154   -void spi_free_slave(struct spi_slave *slave)
  154 +void tegra20_spi_free_slave(struct spi_slave *slave)
155 155 {
156 156 struct tegra_spi_slave *spi = to_tegra_spi(slave);
157 157  
158 158 free(spi);
159 159 }
160 160  
161   -void spi_init(void)
  161 +int tegra20_spi_init(int *node_list, int count)
162 162 {
163 163 struct tegra_spi_ctrl *ctrl;
164 164 int i;
165 165 int node = 0;
166   - int count;
167   - int node_list[1];
  166 + int found = 0;
168 167  
169   - count = fdtdec_find_aliases_for_id(gd->fdt_blob, "spi",
170   - COMPAT_NVIDIA_TEGRA20_SFLASH,
171   - node_list,
172   - 1);
173 168 for (i = 0; i < count; i++) {
174 169 ctrl = &spi_ctrls[i];
175 170 node = node_list[i];
176 171  
177 172  
... ... @@ -193,13 +188,15 @@
193 188 continue;
194 189 }
195 190 ctrl->valid = 1;
  191 + found = 1;
196 192  
197 193 debug("%s: found controller at %p, freq = %u, periph_id = %d\n",
198 194 __func__, ctrl->regs, ctrl->freq, ctrl->periph_id);
199 195 }
  196 + return !found;
200 197 }
201 198  
202   -int spi_claim_bus(struct spi_slave *slave)
  199 +int tegra20_spi_claim_bus(struct spi_slave *slave)
203 200 {
204 201 struct tegra_spi_slave *spi = to_tegra_spi(slave);
205 202 struct spi_regs *regs = spi->ctrl->regs;
... ... @@ -213,7 +210,7 @@
213 210 reg = SPI_STAT_RDY | SPI_STAT_RXF_FLUSH | SPI_STAT_TXF_FLUSH | \
214 211 SPI_STAT_RXF_UNR | SPI_STAT_TXF_OVF;
215 212 writel(reg, &regs->status);
216   - debug("spi_init: STATUS = %08x\n", readl(&regs->status));
  213 + debug("%s: STATUS = %08x\n", __func__, readl(&regs->status));
217 214  
218 215 /*
219 216 * Use sw-controlled CS, so we can clock in data after ReadID, etc.
... ... @@ -223,7 +220,7 @@
223 220 reg |= 1 << SPI_CMD_ACTIVE_SCLK_SHIFT;
224 221 clrsetbits_le32(&regs->command, SPI_CMD_ACTIVE_SCLK_MASK |
225 222 SPI_CMD_ACTIVE_SDA_MASK, SPI_CMD_CS_SOFT | reg);
226   - debug("spi_init: COMMAND = %08x\n", readl(&regs->command));
  223 + debug("%s: COMMAND = %08x\n", __func__, readl(&regs->command));
227 224  
228 225 /*
229 226 * SPI pins on Tegra20 are muxed - change pinmux later due to UART
230 227  
... ... @@ -236,18 +233,8 @@
236 233 return 0;
237 234 }
238 235  
239   -void spi_release_bus(struct spi_slave *slave)
  236 +void tegra20_spi_cs_activate(struct spi_slave *slave)
240 237 {
241   - /*
242   - * We can't release UART_DISABLE and set pinmux to UART4 here since
243   - * some code (e,g, spi_flash_probe) uses printf() while the SPI
244   - * bus is held. That is arguably bad, but it has the advantage of
245   - * already being in the source tree.
246   - */
247   -}
248   -
249   -void spi_cs_activate(struct spi_slave *slave)
250   -{
251 238 struct tegra_spi_slave *spi = to_tegra_spi(slave);
252 239 struct spi_regs *regs = spi->ctrl->regs;
253 240  
... ... @@ -255,7 +242,7 @@
255 242 setbits_le32(&regs->command, SPI_CMD_CS_VAL);
256 243 }
257 244  
258   -void spi_cs_deactivate(struct spi_slave *slave)
  245 +void tegra20_spi_cs_deactivate(struct spi_slave *slave)
259 246 {
260 247 struct tegra_spi_slave *spi = to_tegra_spi(slave);
261 248 struct spi_regs *regs = spi->ctrl->regs;
... ... @@ -264,7 +251,7 @@
264 251 clrbits_le32(&regs->command, SPI_CMD_CS_VAL);
265 252 }
266 253  
267   -int spi_xfer(struct spi_slave *slave, unsigned int bitlen,
  254 +int tegra20_spi_xfer(struct spi_slave *slave, unsigned int bitlen,
268 255 const void *data_out, void *data_in, unsigned long flags)
269 256 {
270 257 struct tegra_spi_slave *spi = to_tegra_spi(slave);
drivers/spi/tegra20_slink.c
... ... @@ -107,7 +107,7 @@
107 107 return container_of(slave, struct tegra_spi_slave, slave);
108 108 }
109 109  
110   -int spi_cs_is_valid(unsigned int bus, unsigned int cs)
  110 +int tegra30_spi_cs_is_valid(unsigned int bus, unsigned int cs)
111 111 {
112 112 if (bus >= CONFIG_TEGRA_SLINK_CTRLS || cs > 3 || !spi_ctrls[bus].valid)
113 113 return 0;
... ... @@ -115,7 +115,7 @@
115 115 return 1;
116 116 }
117 117  
118   -struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
  118 +struct spi_slave *tegra30_spi_setup_slave(unsigned int bus, unsigned int cs,
119 119 unsigned int max_hz, unsigned int mode)
120 120 {
121 121 struct tegra_spi_slave *spi;
122 122  
123 123  
124 124  
... ... @@ -159,25 +159,20 @@
159 159 return &spi->slave;
160 160 }
161 161  
162   -void spi_free_slave(struct spi_slave *slave)
  162 +void tegra30_spi_free_slave(struct spi_slave *slave)
163 163 {
164 164 struct tegra_spi_slave *spi = to_tegra_spi(slave);
165 165  
166 166 free(spi);
167 167 }
168 168  
169   -void spi_init(void)
  169 +int tegra30_spi_init(int *node_list, int count)
170 170 {
171 171 struct tegra_spi_ctrl *ctrl;
172 172 int i;
173 173 int node = 0;
174   - int count;
175   - int node_list[CONFIG_TEGRA_SLINK_CTRLS];
  174 + int found = 0;
176 175  
177   - count = fdtdec_find_aliases_for_id(gd->fdt_blob, "spi",
178   - COMPAT_NVIDIA_TEGRA20_SLINK,
179   - node_list,
180   - CONFIG_TEGRA_SLINK_CTRLS);
181 176 for (i = 0; i < count; i++) {
182 177 ctrl = &spi_ctrls[i];
183 178 node = node_list[i];
184 179  
185 180  
... ... @@ -201,13 +196,15 @@
201 196 continue;
202 197 }
203 198 ctrl->valid = 1;
  199 + found = 1;
204 200  
205 201 debug("%s: found controller at %p, freq = %u, periph_id = %d\n",
206 202 __func__, ctrl->regs, ctrl->freq, ctrl->periph_id);
207 203 }
  204 + return !found;
208 205 }
209 206  
210   -int spi_claim_bus(struct spi_slave *slave)
  207 +int tegra30_spi_claim_bus(struct spi_slave *slave)
211 208 {
212 209 struct tegra_spi_slave *spi = to_tegra_spi(slave);
213 210 struct spi_regs *regs = spi->ctrl->regs;
214 211  
... ... @@ -232,12 +229,8 @@
232 229 return 0;
233 230 }
234 231  
235   -void spi_release_bus(struct spi_slave *slave)
  232 +void tegra30_spi_cs_activate(struct spi_slave *slave)
236 233 {
237   -}
238   -
239   -void spi_cs_activate(struct spi_slave *slave)
240   -{
241 234 struct tegra_spi_slave *spi = to_tegra_spi(slave);
242 235 struct spi_regs *regs = spi->ctrl->regs;
243 236  
... ... @@ -245,7 +238,7 @@
245 238 setbits_le32(&regs->command, SLINK_CMD_CS_VAL);
246 239 }
247 240  
248   -void spi_cs_deactivate(struct spi_slave *slave)
  241 +void tegra30_spi_cs_deactivate(struct spi_slave *slave)
249 242 {
250 243 struct tegra_spi_slave *spi = to_tegra_spi(slave);
251 244 struct spi_regs *regs = spi->ctrl->regs;
... ... @@ -254,7 +247,7 @@
254 247 clrbits_le32(&regs->command, SLINK_CMD_CS_VAL);
255 248 }
256 249  
257   -int spi_xfer(struct spi_slave *slave, unsigned int bitlen,
  250 +int tegra30_spi_xfer(struct spi_slave *slave, unsigned int bitlen,
258 251 const void *data_out, void *data_in, unsigned long flags)
259 252 {
260 253 struct tegra_spi_slave *spi = to_tegra_spi(slave);
include/configs/tegra-common-post.h
... ... @@ -150,6 +150,10 @@
150 150 MEM_LAYOUT_ENV_SETTINGS \
151 151 BOOTCMDS_COMMON
152 152  
  153 +#if defined(CONFIG_TEGRA20_SFLASH) || defined(CONFIG_TEGRA20_SLINK)
  154 +#define CONFIG_FDT_SPI
  155 +#endif
  156 +
153 157 /* overrides for SPL build here */
154 158 #ifdef CONFIG_SPL_BUILD
155 159