aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/spi
diff options
context:
space:
mode:
authorUwe Kleine-König <u.kleine-koenig@pengutronix.de>2010-09-09 09:29:01 -0400
committerSascha Hauer <s.hauer@pengutronix.de>2010-10-01 03:32:11 -0400
commitf4ba6315cb77a5dcff6664ce1d66ebfe31bcc6b1 (patch)
treec0c99772309192bf7c5eb120fe7f0ea8af1dc160 /drivers/spi
parente89524d33deb55de28b4ab171e4b0f89d46b2d4e (diff)
spi/imx: convert driver to use platform ids
This has the advantage not to need to much cpu_is_... macros. Still more when imx51 support is added which has two different spi interfaces which would introduce additional checks on the device id. With this setup it's not possible for the compiler anymore to detect the unused functions, so four additional kconfig symbols are introduced to ifdef out the unneeded functions in the callback array and all these functions are marked with __maybe_unused to suppress the corresponding gcc warnings. Comparing the driver footprint with and without the patch for a mx27 kernel yields: add/remove: 2/0 grow/shrink: 2/0 up/down: 280/0 (280) function old new delta spi_imx_devtype - 192 +192 spi_imx_probe 980 1032 +52 spi_imx_devtype_data - 32 +32 spi_imx_setupxfer 276 280 +4 Later when the platform code is updated to use the platform ids, the autodetection can be removed which will make the driver a bit smaller again. (~60 Bytes in my test.) Acked-by: Jason Wang <jason77.wang@gmail.com> Acked-by: Grant Likely <grant.likely@secretlab.ca> Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Diffstat (limited to 'drivers/spi')
-rw-r--r--drivers/spi/Kconfig12
-rw-r--r--drivers/spi/spi_imx.c173
2 files changed, 143 insertions, 42 deletions
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index 30aea6de4e37..4e9d77bc7d2f 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -143,6 +143,18 @@ config SPI_GPIO
143 GPIO operations, you should be able to leverage that for better 143 GPIO operations, you should be able to leverage that for better
144 speed with a custom version of this driver; see the source code. 144 speed with a custom version of this driver; see the source code.
145 145
146config SPI_IMX_VER_IMX1
147 def_bool y if SOC_IMX1
148
149config SPI_IMX_VER_0_0
150 def_bool y if SOC_IMX21 || SOC_IMX27
151
152config SPI_IMX_VER_0_4
153 def_bool y if ARCH_MX31
154
155config SPI_IMX_VER_0_7
156 def_bool y if ARCH_MX25 || ARCH_MX35
157
146config SPI_IMX 158config SPI_IMX
147 tristate "Freescale i.MX SPI controllers" 159 tristate "Freescale i.MX SPI controllers"
148 depends on ARCH_MXC 160 depends on ARCH_MXC
diff --git a/drivers/spi/spi_imx.c b/drivers/spi/spi_imx.c
index 7972e9077473..20cdee3b5a2e 100644
--- a/drivers/spi/spi_imx.c
+++ b/drivers/spi/spi_imx.c
@@ -59,6 +59,24 @@ struct spi_imx_config {
59 int cs; 59 int cs;
60}; 60};
61 61
62enum spi_imx_devtype {
63 SPI_IMX_VER_IMX1,
64 SPI_IMX_VER_0_0,
65 SPI_IMX_VER_0_4,
66 SPI_IMX_VER_0_5,
67 SPI_IMX_VER_0_7,
68 SPI_IMX_VER_AUTODETECT,
69};
70
71struct spi_imx_data;
72
73struct spi_imx_devtype_data {
74 void (*intctrl)(struct spi_imx_data *, int);
75 int (*config)(struct spi_imx_data *, struct spi_imx_config *);
76 void (*trigger)(struct spi_imx_data *);
77 int (*rx_available)(struct spi_imx_data *);
78};
79
62struct spi_imx_data { 80struct spi_imx_data {
63 struct spi_bitbang bitbang; 81 struct spi_bitbang bitbang;
64 82
@@ -76,11 +94,7 @@ struct spi_imx_data {
76 const void *tx_buf; 94 const void *tx_buf;
77 unsigned int txfifo; /* number of words pushed in tx FIFO */ 95 unsigned int txfifo; /* number of words pushed in tx FIFO */
78 96
79 /* SoC specific functions */ 97 struct spi_imx_devtype_data devtype_data;
80 void (*intctrl)(struct spi_imx_data *, int);
81 int (*config)(struct spi_imx_data *, struct spi_imx_config *);
82 void (*trigger)(struct spi_imx_data *);
83 int (*rx_available)(struct spi_imx_data *);
84}; 98};
85 99
86#define MXC_SPI_BUF_RX(type) \ 100#define MXC_SPI_BUF_RX(type) \
@@ -178,7 +192,7 @@ static unsigned int spi_imx_clkdiv_2(unsigned int fin,
178 * the i.MX35 has a slightly different register layout for bits 192 * the i.MX35 has a slightly different register layout for bits
179 * we do not use here. 193 * we do not use here.
180 */ 194 */
181static void mx31_intctrl(struct spi_imx_data *spi_imx, int enable) 195static void __maybe_unused mx31_intctrl(struct spi_imx_data *spi_imx, int enable)
182{ 196{
183 unsigned int val = 0; 197 unsigned int val = 0;
184 198
@@ -190,7 +204,7 @@ static void mx31_intctrl(struct spi_imx_data *spi_imx, int enable)
190 writel(val, spi_imx->base + MXC_CSPIINT); 204 writel(val, spi_imx->base + MXC_CSPIINT);
191} 205}
192 206
193static void mx31_trigger(struct spi_imx_data *spi_imx) 207static void __maybe_unused mx31_trigger(struct spi_imx_data *spi_imx)
194{ 208{
195 unsigned int reg; 209 unsigned int reg;
196 210
@@ -199,7 +213,7 @@ static void mx31_trigger(struct spi_imx_data *spi_imx)
199 writel(reg, spi_imx->base + MXC_CSPICTRL); 213 writel(reg, spi_imx->base + MXC_CSPICTRL);
200} 214}
201 215
202static int mx31_config(struct spi_imx_data *spi_imx, 216static int __maybe_unused mx31_config(struct spi_imx_data *spi_imx,
203 struct spi_imx_config *config) 217 struct spi_imx_config *config)
204{ 218{
205 unsigned int reg = MX31_CSPICTRL_ENABLE | MX31_CSPICTRL_MASTER; 219 unsigned int reg = MX31_CSPICTRL_ENABLE | MX31_CSPICTRL_MASTER;
@@ -232,7 +246,7 @@ static int mx31_config(struct spi_imx_data *spi_imx,
232 return 0; 246 return 0;
233} 247}
234 248
235static int mx31_rx_available(struct spi_imx_data *spi_imx) 249static int __maybe_unused mx31_rx_available(struct spi_imx_data *spi_imx)
236{ 250{
237 return readl(spi_imx->base + MX31_CSPISTATUS) & MX31_STATUS_RR; 251 return readl(spi_imx->base + MX31_CSPISTATUS) & MX31_STATUS_RR;
238} 252}
@@ -250,7 +264,7 @@ static int mx31_rx_available(struct spi_imx_data *spi_imx)
250#define MX27_CSPICTRL_DR_SHIFT 14 264#define MX27_CSPICTRL_DR_SHIFT 14
251#define MX27_CSPICTRL_CS_SHIFT 19 265#define MX27_CSPICTRL_CS_SHIFT 19
252 266
253static void mx27_intctrl(struct spi_imx_data *spi_imx, int enable) 267static void __maybe_unused mx27_intctrl(struct spi_imx_data *spi_imx, int enable)
254{ 268{
255 unsigned int val = 0; 269 unsigned int val = 0;
256 270
@@ -262,7 +276,7 @@ static void mx27_intctrl(struct spi_imx_data *spi_imx, int enable)
262 writel(val, spi_imx->base + MXC_CSPIINT); 276 writel(val, spi_imx->base + MXC_CSPIINT);
263} 277}
264 278
265static void mx27_trigger(struct spi_imx_data *spi_imx) 279static void __maybe_unused mx27_trigger(struct spi_imx_data *spi_imx)
266{ 280{
267 unsigned int reg; 281 unsigned int reg;
268 282
@@ -271,7 +285,7 @@ static void mx27_trigger(struct spi_imx_data *spi_imx)
271 writel(reg, spi_imx->base + MXC_CSPICTRL); 285 writel(reg, spi_imx->base + MXC_CSPICTRL);
272} 286}
273 287
274static int mx27_config(struct spi_imx_data *spi_imx, 288static int __maybe_unused mx27_config(struct spi_imx_data *spi_imx,
275 struct spi_imx_config *config) 289 struct spi_imx_config *config)
276{ 290{
277 unsigned int reg = MX27_CSPICTRL_ENABLE | MX27_CSPICTRL_MASTER; 291 unsigned int reg = MX27_CSPICTRL_ENABLE | MX27_CSPICTRL_MASTER;
@@ -294,7 +308,7 @@ static int mx27_config(struct spi_imx_data *spi_imx,
294 return 0; 308 return 0;
295} 309}
296 310
297static int mx27_rx_available(struct spi_imx_data *spi_imx) 311static int __maybe_unused mx27_rx_available(struct spi_imx_data *spi_imx)
298{ 312{
299 return readl(spi_imx->base + MXC_CSPIINT) & MX27_INTREG_RR; 313 return readl(spi_imx->base + MXC_CSPIINT) & MX27_INTREG_RR;
300} 314}
@@ -310,7 +324,7 @@ static int mx27_rx_available(struct spi_imx_data *spi_imx)
310#define MX1_CSPICTRL_MASTER (1 << 10) 324#define MX1_CSPICTRL_MASTER (1 << 10)
311#define MX1_CSPICTRL_DR_SHIFT 13 325#define MX1_CSPICTRL_DR_SHIFT 13
312 326
313static void mx1_intctrl(struct spi_imx_data *spi_imx, int enable) 327static void __maybe_unused mx1_intctrl(struct spi_imx_data *spi_imx, int enable)
314{ 328{
315 unsigned int val = 0; 329 unsigned int val = 0;
316 330
@@ -322,7 +336,7 @@ static void mx1_intctrl(struct spi_imx_data *spi_imx, int enable)
322 writel(val, spi_imx->base + MXC_CSPIINT); 336 writel(val, spi_imx->base + MXC_CSPIINT);
323} 337}
324 338
325static void mx1_trigger(struct spi_imx_data *spi_imx) 339static void __maybe_unused mx1_trigger(struct spi_imx_data *spi_imx)
326{ 340{
327 unsigned int reg; 341 unsigned int reg;
328 342
@@ -331,7 +345,7 @@ static void mx1_trigger(struct spi_imx_data *spi_imx)
331 writel(reg, spi_imx->base + MXC_CSPICTRL); 345 writel(reg, spi_imx->base + MXC_CSPICTRL);
332} 346}
333 347
334static int mx1_config(struct spi_imx_data *spi_imx, 348static int __maybe_unused mx1_config(struct spi_imx_data *spi_imx,
335 struct spi_imx_config *config) 349 struct spi_imx_config *config)
336{ 350{
337 unsigned int reg = MX1_CSPICTRL_ENABLE | MX1_CSPICTRL_MASTER; 351 unsigned int reg = MX1_CSPICTRL_ENABLE | MX1_CSPICTRL_MASTER;
@@ -350,11 +364,50 @@ static int mx1_config(struct spi_imx_data *spi_imx,
350 return 0; 364 return 0;
351} 365}
352 366
353static int mx1_rx_available(struct spi_imx_data *spi_imx) 367static int __maybe_unused mx1_rx_available(struct spi_imx_data *spi_imx)
354{ 368{
355 return readl(spi_imx->base + MXC_CSPIINT) & MX1_INTREG_RR; 369 return readl(spi_imx->base + MXC_CSPIINT) & MX1_INTREG_RR;
356} 370}
357 371
372/*
373 * These version numbers are taken from the Freescale driver. Unfortunately it
374 * doesn't support i.MX1, so this entry doesn't match the scheme. :-(
375 */
376static struct spi_imx_devtype_data spi_imx_devtype_data[] __devinitdata = {
377#ifdef CONFIG_SPI_IMX_VER_IMX1
378 [SPI_IMX_VER_IMX1] = {
379 .intctrl = mx1_intctrl,
380 .config = mx1_config,
381 .trigger = mx1_trigger,
382 .rx_available = mx1_rx_available,
383 },
384#endif
385#ifdef CONFIG_SPI_IMX_VER_0_0
386 [SPI_IMX_VER_0_0] = {
387 .intctrl = mx27_intctrl,
388 .config = mx27_config,
389 .trigger = mx27_trigger,
390 .rx_available = mx27_rx_available,
391 },
392#endif
393#ifdef CONFIG_SPI_IMX_VER_0_4
394 [SPI_IMX_VER_0_4] = {
395 .intctrl = mx31_intctrl,
396 .config = mx31_config,
397 .trigger = mx31_trigger,
398 .rx_available = mx31_rx_available,
399 },
400#endif
401#ifdef CONFIG_SPI_IMX_VER_0_7
402 [SPI_IMX_VER_0_7] = {
403 .intctrl = mx31_intctrl,
404 .config = mx31_config,
405 .trigger = mx31_trigger,
406 .rx_available = mx31_rx_available,
407 },
408#endif
409};
410
358static void spi_imx_chipselect(struct spi_device *spi, int is_active) 411static void spi_imx_chipselect(struct spi_device *spi, int is_active)
359{ 412{
360 struct spi_imx_data *spi_imx = spi_master_get_devdata(spi->master); 413 struct spi_imx_data *spi_imx = spi_master_get_devdata(spi->master);
@@ -377,14 +430,14 @@ static void spi_imx_push(struct spi_imx_data *spi_imx)
377 spi_imx->txfifo++; 430 spi_imx->txfifo++;
378 } 431 }
379 432
380 spi_imx->trigger(spi_imx); 433 spi_imx->devtype_data.trigger(spi_imx);
381} 434}
382 435
383static irqreturn_t spi_imx_isr(int irq, void *dev_id) 436static irqreturn_t spi_imx_isr(int irq, void *dev_id)
384{ 437{
385 struct spi_imx_data *spi_imx = dev_id; 438 struct spi_imx_data *spi_imx = dev_id;
386 439
387 while (spi_imx->rx_available(spi_imx)) { 440 while (spi_imx->devtype_data.rx_available(spi_imx)) {
388 spi_imx->rx(spi_imx); 441 spi_imx->rx(spi_imx);
389 spi_imx->txfifo--; 442 spi_imx->txfifo--;
390 } 443 }
@@ -398,11 +451,12 @@ static irqreturn_t spi_imx_isr(int irq, void *dev_id)
398 /* No data left to push, but still waiting for rx data, 451 /* No data left to push, but still waiting for rx data,
399 * enable receive data available interrupt. 452 * enable receive data available interrupt.
400 */ 453 */
401 spi_imx->intctrl(spi_imx, MXC_INT_RR); 454 spi_imx->devtype_data.intctrl(
455 spi_imx, MXC_INT_RR);
402 return IRQ_HANDLED; 456 return IRQ_HANDLED;
403 } 457 }
404 458
405 spi_imx->intctrl(spi_imx, 0); 459 spi_imx->devtype_data.intctrl(spi_imx, 0);
406 complete(&spi_imx->xfer_done); 460 complete(&spi_imx->xfer_done);
407 461
408 return IRQ_HANDLED; 462 return IRQ_HANDLED;
@@ -439,7 +493,7 @@ static int spi_imx_setupxfer(struct spi_device *spi,
439 } else 493 } else
440 BUG(); 494 BUG();
441 495
442 spi_imx->config(spi_imx, &config); 496 spi_imx->devtype_data.config(spi_imx, &config);
443 497
444 return 0; 498 return 0;
445} 499}
@@ -458,7 +512,7 @@ static int spi_imx_transfer(struct spi_device *spi,
458 512
459 spi_imx_push(spi_imx); 513 spi_imx_push(spi_imx);
460 514
461 spi_imx->intctrl(spi_imx, MXC_INT_TE); 515 spi_imx->devtype_data.intctrl(spi_imx, MXC_INT_TE);
462 516
463 wait_for_completion(&spi_imx->xfer_done); 517 wait_for_completion(&spi_imx->xfer_done);
464 518
@@ -485,6 +539,33 @@ static void spi_imx_cleanup(struct spi_device *spi)
485{ 539{
486} 540}
487 541
542static struct platform_device_id spi_imx_devtype[] = {
543 {
544 .name = DRIVER_NAME,
545 .driver_data = SPI_IMX_VER_AUTODETECT,
546 }, {
547 .name = "imx1-cspi",
548 .driver_data = SPI_IMX_VER_IMX1,
549 }, {
550 .name = "imx21-cspi",
551 .driver_data = SPI_IMX_VER_0_0,
552 }, {
553 .name = "imx25-cspi",
554 .driver_data = SPI_IMX_VER_0_7,
555 }, {
556 .name = "imx27-cspi",
557 .driver_data = SPI_IMX_VER_0_0,
558 }, {
559 .name = "imx31-cspi",
560 .driver_data = SPI_IMX_VER_0_4,
561 }, {
562 .name = "imx35-cspi",
563 .driver_data = SPI_IMX_VER_0_7,
564 }, {
565 /* sentinel */
566 }
567};
568
488static int __devinit spi_imx_probe(struct platform_device *pdev) 569static int __devinit spi_imx_probe(struct platform_device *pdev)
489{ 570{
490 struct spi_imx_master *mxc_platform_info; 571 struct spi_imx_master *mxc_platform_info;
@@ -536,6 +617,31 @@ static int __devinit spi_imx_probe(struct platform_device *pdev)
536 617
537 init_completion(&spi_imx->xfer_done); 618 init_completion(&spi_imx->xfer_done);
538 619
620 if (pdev->id_entry->driver_data == SPI_IMX_VER_AUTODETECT) {
621 if (cpu_is_mx25() || cpu_is_mx35())
622 spi_imx->devtype_data =
623 spi_imx_devtype_data[SPI_IMX_VER_0_7];
624 else if (cpu_is_mx25() || cpu_is_mx31() || cpu_is_mx35())
625 spi_imx->devtype_data =
626 spi_imx_devtype_data[SPI_IMX_VER_0_4];
627 else if (cpu_is_mx27() || cpu_is_mx21())
628 spi_imx->devtype_data =
629 spi_imx_devtype_data[SPI_IMX_VER_0_0];
630 else if (cpu_is_mx1())
631 spi_imx->devtype_data =
632 spi_imx_devtype_data[SPI_IMX_VER_IMX1];
633 else
634 BUG();
635 } else
636 spi_imx->devtype_data =
637 spi_imx_devtype_data[pdev->id_entry->driver_data];
638
639 if (!spi_imx->devtype_data.intctrl) {
640 dev_err(&pdev->dev, "no support for this device compiled in\n");
641 ret = -ENODEV;
642 goto out_gpio_free;
643 }
644
539 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 645 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
540 if (!res) { 646 if (!res) {
541 dev_err(&pdev->dev, "can't get platform resource\n"); 647 dev_err(&pdev->dev, "can't get platform resource\n");
@@ -567,24 +673,6 @@ static int __devinit spi_imx_probe(struct platform_device *pdev)
567 goto out_iounmap; 673 goto out_iounmap;
568 } 674 }
569 675
570 if (cpu_is_mx25() || cpu_is_mx31() || cpu_is_mx35()) {
571 spi_imx->intctrl = mx31_intctrl;
572 spi_imx->config = mx31_config;
573 spi_imx->trigger = mx31_trigger;
574 spi_imx->rx_available = mx31_rx_available;
575 } else if (cpu_is_mx27() || cpu_is_mx21()) {
576 spi_imx->intctrl = mx27_intctrl;
577 spi_imx->config = mx27_config;
578 spi_imx->trigger = mx27_trigger;
579 spi_imx->rx_available = mx27_rx_available;
580 } else if (cpu_is_mx1()) {
581 spi_imx->intctrl = mx1_intctrl;
582 spi_imx->config = mx1_config;
583 spi_imx->trigger = mx1_trigger;
584 spi_imx->rx_available = mx1_rx_available;
585 } else
586 BUG();
587
588 spi_imx->clk = clk_get(&pdev->dev, NULL); 676 spi_imx->clk = clk_get(&pdev->dev, NULL);
589 if (IS_ERR(spi_imx->clk)) { 677 if (IS_ERR(spi_imx->clk)) {
590 dev_err(&pdev->dev, "unable to get clock\n"); 678 dev_err(&pdev->dev, "unable to get clock\n");
@@ -603,7 +691,7 @@ static int __devinit spi_imx_probe(struct platform_device *pdev)
603 while (readl(spi_imx->base + MX3_CSPISTAT) & MX3_CSPISTAT_RR) 691 while (readl(spi_imx->base + MX3_CSPISTAT) & MX3_CSPISTAT_RR)
604 readl(spi_imx->base + MXC_CSPIRXDATA); 692 readl(spi_imx->base + MXC_CSPIRXDATA);
605 693
606 spi_imx->intctrl(spi_imx, 0); 694 spi_imx->devtype_data.intctrl(spi_imx, 0);
607 695
608 ret = spi_bitbang_start(&spi_imx->bitbang); 696 ret = spi_bitbang_start(&spi_imx->bitbang);
609 if (ret) { 697 if (ret) {
@@ -668,6 +756,7 @@ static struct platform_driver spi_imx_driver = {
668 .name = DRIVER_NAME, 756 .name = DRIVER_NAME,
669 .owner = THIS_MODULE, 757 .owner = THIS_MODULE,
670 }, 758 },
759 .id_table = spi_imx_devtype,
671 .probe = spi_imx_probe, 760 .probe = spi_imx_probe,
672 .remove = __devexit_p(spi_imx_remove), 761 .remove = __devexit_p(spi_imx_remove),
673}; 762};