aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/mips/bcm63xx/dev-spi.c34
-rw-r--r--arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_spi.h42
-rw-r--r--drivers/spi/Kconfig2
-rw-r--r--drivers/spi/spi-bcm63xx.c197
4 files changed, 181 insertions, 94 deletions
diff --git a/arch/mips/bcm63xx/dev-spi.c b/arch/mips/bcm63xx/dev-spi.c
index b21225647e03..232385441e46 100644
--- a/arch/mips/bcm63xx/dev-spi.c
+++ b/arch/mips/bcm63xx/dev-spi.c
@@ -18,29 +18,6 @@
18#include <bcm63xx_dev_spi.h> 18#include <bcm63xx_dev_spi.h>
19#include <bcm63xx_regs.h> 19#include <bcm63xx_regs.h>
20 20
21/*
22 * register offsets
23 */
24static const unsigned long bcm6348_regs_spi[] = {
25 __GEN_SPI_REGS_TABLE(6348)
26};
27
28static const unsigned long bcm6358_regs_spi[] = {
29 __GEN_SPI_REGS_TABLE(6358)
30};
31
32const unsigned long *bcm63xx_regs_spi;
33EXPORT_SYMBOL(bcm63xx_regs_spi);
34
35static __init void bcm63xx_spi_regs_init(void)
36{
37 if (BCMCPU_IS_6338() || BCMCPU_IS_6348())
38 bcm63xx_regs_spi = bcm6348_regs_spi;
39 if (BCMCPU_IS_3368() || BCMCPU_IS_6358() ||
40 BCMCPU_IS_6362() || BCMCPU_IS_6368())
41 bcm63xx_regs_spi = bcm6358_regs_spi;
42}
43
44static struct resource spi_resources[] = { 21static struct resource spi_resources[] = {
45 { 22 {
46 .start = -1, /* filled at runtime */ 23 .start = -1, /* filled at runtime */
@@ -54,7 +31,6 @@ static struct resource spi_resources[] = {
54}; 31};
55 32
56static struct platform_device bcm63xx_spi_device = { 33static struct platform_device bcm63xx_spi_device = {
57 .name = "bcm63xx-spi",
58 .id = -1, 34 .id = -1,
59 .num_resources = ARRAY_SIZE(spi_resources), 35 .num_resources = ARRAY_SIZE(spi_resources),
60 .resource = spi_resources, 36 .resource = spi_resources,
@@ -69,14 +45,16 @@ int __init bcm63xx_spi_register(void)
69 spi_resources[0].end = spi_resources[0].start; 45 spi_resources[0].end = spi_resources[0].start;
70 spi_resources[1].start = bcm63xx_get_irq_number(IRQ_SPI); 46 spi_resources[1].start = bcm63xx_get_irq_number(IRQ_SPI);
71 47
72 if (BCMCPU_IS_6338() || BCMCPU_IS_6348()) 48 if (BCMCPU_IS_6338() || BCMCPU_IS_6348()) {
49 bcm63xx_spi_device.name = "bcm6348-spi",
73 spi_resources[0].end += BCM_6348_RSET_SPI_SIZE - 1; 50 spi_resources[0].end += BCM_6348_RSET_SPI_SIZE - 1;
51 }
74 52
75 if (BCMCPU_IS_3368() || BCMCPU_IS_6358() || BCMCPU_IS_6362() || 53 if (BCMCPU_IS_3368() || BCMCPU_IS_6358() || BCMCPU_IS_6362() ||
76 BCMCPU_IS_6368()) 54 BCMCPU_IS_6368()) {
55 bcm63xx_spi_device.name = "bcm6358-spi",
77 spi_resources[0].end += BCM_6358_RSET_SPI_SIZE - 1; 56 spi_resources[0].end += BCM_6358_RSET_SPI_SIZE - 1;
78 57 }
79 bcm63xx_spi_regs_init();
80 58
81 return platform_device_register(&bcm63xx_spi_device); 59 return platform_device_register(&bcm63xx_spi_device);
82} 60}
diff --git a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_spi.h b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_spi.h
index 1d121fd5b6f5..dd299548860d 100644
--- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_spi.h
+++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_spi.h
@@ -7,46 +7,4 @@
7 7
8int __init bcm63xx_spi_register(void); 8int __init bcm63xx_spi_register(void);
9 9
10enum bcm63xx_regs_spi {
11 SPI_CMD,
12 SPI_INT_STATUS,
13 SPI_INT_MASK_ST,
14 SPI_INT_MASK,
15 SPI_ST,
16 SPI_CLK_CFG,
17 SPI_FILL_BYTE,
18 SPI_MSG_TAIL,
19 SPI_RX_TAIL,
20 SPI_MSG_CTL,
21 SPI_MSG_DATA,
22 SPI_RX_DATA,
23 SPI_MSG_TYPE_SHIFT,
24 SPI_MSG_CTL_WIDTH,
25 SPI_MSG_DATA_SIZE,
26};
27
28#define __GEN_SPI_REGS_TABLE(__cpu) \
29 [SPI_CMD] = SPI_## __cpu ##_CMD, \
30 [SPI_INT_STATUS] = SPI_## __cpu ##_INT_STATUS, \
31 [SPI_INT_MASK_ST] = SPI_## __cpu ##_INT_MASK_ST, \
32 [SPI_INT_MASK] = SPI_## __cpu ##_INT_MASK, \
33 [SPI_ST] = SPI_## __cpu ##_ST, \
34 [SPI_CLK_CFG] = SPI_## __cpu ##_CLK_CFG, \
35 [SPI_FILL_BYTE] = SPI_## __cpu ##_FILL_BYTE, \
36 [SPI_MSG_TAIL] = SPI_## __cpu ##_MSG_TAIL, \
37 [SPI_RX_TAIL] = SPI_## __cpu ##_RX_TAIL, \
38 [SPI_MSG_CTL] = SPI_## __cpu ##_MSG_CTL, \
39 [SPI_MSG_DATA] = SPI_## __cpu ##_MSG_DATA, \
40 [SPI_RX_DATA] = SPI_## __cpu ##_RX_DATA, \
41 [SPI_MSG_TYPE_SHIFT] = SPI_## __cpu ##_MSG_TYPE_SHIFT, \
42 [SPI_MSG_CTL_WIDTH] = SPI_## __cpu ##_MSG_CTL_WIDTH, \
43 [SPI_MSG_DATA_SIZE] = SPI_## __cpu ##_MSG_DATA_SIZE,
44
45static inline unsigned long bcm63xx_spireg(enum bcm63xx_regs_spi reg)
46{
47 extern const unsigned long *bcm63xx_regs_spi;
48
49 return bcm63xx_regs_spi[reg];
50}
51
52#endif /* BCM63XX_DEV_SPI_H */ 10#endif /* BCM63XX_DEV_SPI_H */
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index 4887f317ea58..5c1db987beff 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -125,7 +125,7 @@ config SPI_BCM53XX
125 125
126config SPI_BCM63XX 126config SPI_BCM63XX
127 tristate "Broadcom BCM63xx SPI controller" 127 tristate "Broadcom BCM63xx SPI controller"
128 depends on BCM63XX 128 depends on BCM63XX || COMPILE_TEST
129 help 129 help
130 Enable support for the SPI controller on the Broadcom BCM63xx SoCs. 130 Enable support for the SPI controller on the Broadcom BCM63xx SoCs.
131 131
diff --git a/drivers/spi/spi-bcm63xx.c b/drivers/spi/spi-bcm63xx.c
index b3da04494fa9..06858e04ec59 100644
--- a/drivers/spi/spi-bcm63xx.c
+++ b/drivers/spi/spi-bcm63xx.c
@@ -27,7 +27,111 @@
27#include <linux/err.h> 27#include <linux/err.h>
28#include <linux/pm_runtime.h> 28#include <linux/pm_runtime.h>
29 29
30#include <bcm63xx_dev_spi.h> 30/* BCM 6338/6348 SPI core */
31#define SPI_6348_RSET_SIZE 64
32#define SPI_6348_CMD 0x00 /* 16-bits register */
33#define SPI_6348_INT_STATUS 0x02
34#define SPI_6348_INT_MASK_ST 0x03
35#define SPI_6348_INT_MASK 0x04
36#define SPI_6348_ST 0x05
37#define SPI_6348_CLK_CFG 0x06
38#define SPI_6348_FILL_BYTE 0x07
39#define SPI_6348_MSG_TAIL 0x09
40#define SPI_6348_RX_TAIL 0x0b
41#define SPI_6348_MSG_CTL 0x40 /* 8-bits register */
42#define SPI_6348_MSG_CTL_WIDTH 8
43#define SPI_6348_MSG_DATA 0x41
44#define SPI_6348_MSG_DATA_SIZE 0x3f
45#define SPI_6348_RX_DATA 0x80
46#define SPI_6348_RX_DATA_SIZE 0x3f
47
48/* BCM 3368/6358/6262/6368 SPI core */
49#define SPI_6358_RSET_SIZE 1804
50#define SPI_6358_MSG_CTL 0x00 /* 16-bits register */
51#define SPI_6358_MSG_CTL_WIDTH 16
52#define SPI_6358_MSG_DATA 0x02
53#define SPI_6358_MSG_DATA_SIZE 0x21e
54#define SPI_6358_RX_DATA 0x400
55#define SPI_6358_RX_DATA_SIZE 0x220
56#define SPI_6358_CMD 0x700 /* 16-bits register */
57#define SPI_6358_INT_STATUS 0x702
58#define SPI_6358_INT_MASK_ST 0x703
59#define SPI_6358_INT_MASK 0x704
60#define SPI_6358_ST 0x705
61#define SPI_6358_CLK_CFG 0x706
62#define SPI_6358_FILL_BYTE 0x707
63#define SPI_6358_MSG_TAIL 0x709
64#define SPI_6358_RX_TAIL 0x70B
65
66/* Shared SPI definitions */
67
68/* Message configuration */
69#define SPI_FD_RW 0x00
70#define SPI_HD_W 0x01
71#define SPI_HD_R 0x02
72#define SPI_BYTE_CNT_SHIFT 0
73#define SPI_6348_MSG_TYPE_SHIFT 6
74#define SPI_6358_MSG_TYPE_SHIFT 14
75
76/* Command */
77#define SPI_CMD_NOOP 0x00
78#define SPI_CMD_SOFT_RESET 0x01
79#define SPI_CMD_HARD_RESET 0x02
80#define SPI_CMD_START_IMMEDIATE 0x03
81#define SPI_CMD_COMMAND_SHIFT 0
82#define SPI_CMD_COMMAND_MASK 0x000f
83#define SPI_CMD_DEVICE_ID_SHIFT 4
84#define SPI_CMD_PREPEND_BYTE_CNT_SHIFT 8
85#define SPI_CMD_ONE_BYTE_SHIFT 11
86#define SPI_CMD_ONE_WIRE_SHIFT 12
87#define SPI_DEV_ID_0 0
88#define SPI_DEV_ID_1 1
89#define SPI_DEV_ID_2 2
90#define SPI_DEV_ID_3 3
91
92/* Interrupt mask */
93#define SPI_INTR_CMD_DONE 0x01
94#define SPI_INTR_RX_OVERFLOW 0x02
95#define SPI_INTR_TX_UNDERFLOW 0x04
96#define SPI_INTR_TX_OVERFLOW 0x08
97#define SPI_INTR_RX_UNDERFLOW 0x10
98#define SPI_INTR_CLEAR_ALL 0x1f
99
100/* Status */
101#define SPI_RX_EMPTY 0x02
102#define SPI_CMD_BUSY 0x04
103#define SPI_SERIAL_BUSY 0x08
104
105/* Clock configuration */
106#define SPI_CLK_20MHZ 0x00
107#define SPI_CLK_0_391MHZ 0x01
108#define SPI_CLK_0_781MHZ 0x02 /* default */
109#define SPI_CLK_1_563MHZ 0x03
110#define SPI_CLK_3_125MHZ 0x04
111#define SPI_CLK_6_250MHZ 0x05
112#define SPI_CLK_12_50MHZ 0x06
113#define SPI_CLK_MASK 0x07
114#define SPI_SSOFFTIME_MASK 0x38
115#define SPI_SSOFFTIME_SHIFT 3
116#define SPI_BYTE_SWAP 0x80
117
118enum bcm63xx_regs_spi {
119 SPI_CMD,
120 SPI_INT_STATUS,
121 SPI_INT_MASK_ST,
122 SPI_INT_MASK,
123 SPI_ST,
124 SPI_CLK_CFG,
125 SPI_FILL_BYTE,
126 SPI_MSG_TAIL,
127 SPI_RX_TAIL,
128 SPI_MSG_CTL,
129 SPI_MSG_DATA,
130 SPI_RX_DATA,
131 SPI_MSG_TYPE_SHIFT,
132 SPI_MSG_CTL_WIDTH,
133 SPI_MSG_DATA_SIZE,
134};
31 135
32#define BCM63XX_SPI_MAX_PREPEND 15 136#define BCM63XX_SPI_MAX_PREPEND 15
33 137
@@ -41,6 +145,7 @@ struct bcm63xx_spi {
41 int irq; 145 int irq;
42 146
43 /* Platform data */ 147 /* Platform data */
148 const unsigned long *reg_offsets;
44 unsigned fifo_size; 149 unsigned fifo_size;
45 unsigned int msg_type_shift; 150 unsigned int msg_type_shift;
46 unsigned int msg_ctl_width; 151 unsigned int msg_ctl_width;
@@ -54,34 +159,34 @@ struct bcm63xx_spi {
54}; 159};
55 160
56static inline u8 bcm_spi_readb(struct bcm63xx_spi *bs, 161static inline u8 bcm_spi_readb(struct bcm63xx_spi *bs,
57 unsigned int offset) 162 unsigned int offset)
58{ 163{
59 return readb(bs->regs + bcm63xx_spireg(offset)); 164 return readb(bs->regs + bs->reg_offsets[offset]);
60} 165}
61 166
62static inline u16 bcm_spi_readw(struct bcm63xx_spi *bs, 167static inline u16 bcm_spi_readw(struct bcm63xx_spi *bs,
63 unsigned int offset) 168 unsigned int offset)
64{ 169{
65#ifdef CONFIG_CPU_BIG_ENDIAN 170#ifdef CONFIG_CPU_BIG_ENDIAN
66 return ioread16be(bs->regs + bcm63xx_spireg(offset)); 171 return ioread16be(bs->regs + bs->reg_offsets[offset]);
67#else 172#else
68 return readw(bs->regs + bcm63xx_spireg(offset)); 173 return readw(bs->regs + bs->reg_offsets[offset]);
69#endif 174#endif
70} 175}
71 176
72static inline void bcm_spi_writeb(struct bcm63xx_spi *bs, 177static inline void bcm_spi_writeb(struct bcm63xx_spi *bs,
73 u8 value, unsigned int offset) 178 u8 value, unsigned int offset)
74{ 179{
75 writeb(value, bs->regs + bcm63xx_spireg(offset)); 180 writeb(value, bs->regs + bs->reg_offsets[offset]);
76} 181}
77 182
78static inline void bcm_spi_writew(struct bcm63xx_spi *bs, 183static inline void bcm_spi_writew(struct bcm63xx_spi *bs,
79 u16 value, unsigned int offset) 184 u16 value, unsigned int offset)
80{ 185{
81#ifdef CONFIG_CPU_BIG_ENDIAN 186#ifdef CONFIG_CPU_BIG_ENDIAN
82 iowrite16be(value, bs->regs + bcm63xx_spireg(offset)); 187 iowrite16be(value, bs->regs + bs->reg_offsets[offset]);
83#else 188#else
84 writew(value, bs->regs + bcm63xx_spireg(offset)); 189 writew(value, bs->regs + bs->reg_offsets[offset]);
85#endif 190#endif
86} 191}
87 192
@@ -324,10 +429,59 @@ static irqreturn_t bcm63xx_spi_interrupt(int irq, void *dev_id)
324 return IRQ_HANDLED; 429 return IRQ_HANDLED;
325} 430}
326 431
432static const unsigned long bcm6348_spi_reg_offsets[] = {
433 [SPI_CMD] = SPI_6348_CMD,
434 [SPI_INT_STATUS] = SPI_6348_INT_STATUS,
435 [SPI_INT_MASK_ST] = SPI_6348_INT_MASK_ST,
436 [SPI_INT_MASK] = SPI_6348_INT_MASK,
437 [SPI_ST] = SPI_6348_ST,
438 [SPI_CLK_CFG] = SPI_6348_CLK_CFG,
439 [SPI_FILL_BYTE] = SPI_6348_FILL_BYTE,
440 [SPI_MSG_TAIL] = SPI_6348_MSG_TAIL,
441 [SPI_RX_TAIL] = SPI_6348_RX_TAIL,
442 [SPI_MSG_CTL] = SPI_6348_MSG_CTL,
443 [SPI_MSG_DATA] = SPI_6348_MSG_DATA,
444 [SPI_RX_DATA] = SPI_6348_RX_DATA,
445 [SPI_MSG_TYPE_SHIFT] = SPI_6348_MSG_TYPE_SHIFT,
446 [SPI_MSG_CTL_WIDTH] = SPI_6348_MSG_CTL_WIDTH,
447 [SPI_MSG_DATA_SIZE] = SPI_6348_MSG_DATA_SIZE,
448};
449
450static const unsigned long bcm6358_spi_reg_offsets[] = {
451 [SPI_CMD] = SPI_6358_CMD,
452 [SPI_INT_STATUS] = SPI_6358_INT_STATUS,
453 [SPI_INT_MASK_ST] = SPI_6358_INT_MASK_ST,
454 [SPI_INT_MASK] = SPI_6358_INT_MASK,
455 [SPI_ST] = SPI_6358_ST,
456 [SPI_CLK_CFG] = SPI_6358_CLK_CFG,
457 [SPI_FILL_BYTE] = SPI_6358_FILL_BYTE,
458 [SPI_MSG_TAIL] = SPI_6358_MSG_TAIL,
459 [SPI_RX_TAIL] = SPI_6358_RX_TAIL,
460 [SPI_MSG_CTL] = SPI_6358_MSG_CTL,
461 [SPI_MSG_DATA] = SPI_6358_MSG_DATA,
462 [SPI_RX_DATA] = SPI_6358_RX_DATA,
463 [SPI_MSG_TYPE_SHIFT] = SPI_6358_MSG_TYPE_SHIFT,
464 [SPI_MSG_CTL_WIDTH] = SPI_6358_MSG_CTL_WIDTH,
465 [SPI_MSG_DATA_SIZE] = SPI_6358_MSG_DATA_SIZE,
466};
467
468static const struct platform_device_id bcm63xx_spi_dev_match[] = {
469 {
470 .name = "bcm6348-spi",
471 .driver_data = (unsigned long)bcm6348_spi_reg_offsets,
472 },
473 {
474 .name = "bcm6358-spi",
475 .driver_data = (unsigned long)bcm6358_spi_reg_offsets,
476 },
477 {
478 },
479};
327 480
328static int bcm63xx_spi_probe(struct platform_device *pdev) 481static int bcm63xx_spi_probe(struct platform_device *pdev)
329{ 482{
330 struct resource *r; 483 struct resource *r;
484 const unsigned long *bcm63xx_spireg;
331 struct device *dev = &pdev->dev; 485 struct device *dev = &pdev->dev;
332 int irq; 486 int irq;
333 struct spi_master *master; 487 struct spi_master *master;
@@ -335,6 +489,11 @@ static int bcm63xx_spi_probe(struct platform_device *pdev)
335 struct bcm63xx_spi *bs; 489 struct bcm63xx_spi *bs;
336 int ret; 490 int ret;
337 491
492 if (!pdev->id_entry->driver_data)
493 return -EINVAL;
494
495 bcm63xx_spireg = (const unsigned long *)pdev->id_entry->driver_data;
496
338 irq = platform_get_irq(pdev, 0); 497 irq = platform_get_irq(pdev, 0);
339 if (irq < 0) { 498 if (irq < 0) {
340 dev_err(dev, "no irq\n"); 499 dev_err(dev, "no irq\n");
@@ -368,7 +527,8 @@ static int bcm63xx_spi_probe(struct platform_device *pdev)
368 527
369 bs->irq = irq; 528 bs->irq = irq;
370 bs->clk = clk; 529 bs->clk = clk;
371 bs->fifo_size = bcm63xx_spireg(SPI_MSG_DATA_SIZE); 530 bs->reg_offsets = bcm63xx_spireg;
531 bs->fifo_size = bs->reg_offsets[SPI_MSG_DATA_SIZE];
372 532
373 ret = devm_request_irq(&pdev->dev, irq, bcm63xx_spi_interrupt, 0, 533 ret = devm_request_irq(&pdev->dev, irq, bcm63xx_spi_interrupt, 0,
374 pdev->name, master); 534 pdev->name, master);
@@ -383,20 +543,10 @@ static int bcm63xx_spi_probe(struct platform_device *pdev)
383 master->mode_bits = MODEBITS; 543 master->mode_bits = MODEBITS;
384 master->bits_per_word_mask = SPI_BPW_MASK(8); 544 master->bits_per_word_mask = SPI_BPW_MASK(8);
385 master->auto_runtime_pm = true; 545 master->auto_runtime_pm = true;
386 bs->msg_type_shift = bcm63xx_spireg(SPI_MSG_TYPE_SHIFT); 546 bs->msg_type_shift = bs->reg_offsets[SPI_MSG_TYPE_SHIFT];
387 bs->msg_ctl_width = bcm63xx_spireg(SPI_MSG_CTL_WIDTH); 547 bs->msg_ctl_width = bs->reg_offsets[SPI_MSG_CTL_WIDTH];
388 bs->tx_io = (u8 *)(bs->regs + bcm63xx_spireg(SPI_MSG_DATA)); 548 bs->tx_io = (u8 *)(bs->regs + bs->reg_offsets[SPI_MSG_DATA]);
389 bs->rx_io = (const u8 *)(bs->regs + bcm63xx_spireg(SPI_RX_DATA)); 549 bs->rx_io = (const u8 *)(bs->regs + bs->reg_offsets[SPI_RX_DATA]);
390
391 switch (bs->msg_ctl_width) {
392 case 8:
393 case 16:
394 break;
395 default:
396 dev_err(dev, "unsupported MSG_CTL width: %d\n",
397 bs->msg_ctl_width);
398 goto out_err;
399 }
400 550
401 /* Initialize hardware */ 551 /* Initialize hardware */
402 ret = clk_prepare_enable(bs->clk); 552 ret = clk_prepare_enable(bs->clk);
@@ -476,6 +626,7 @@ static struct platform_driver bcm63xx_spi_driver = {
476 .name = "bcm63xx-spi", 626 .name = "bcm63xx-spi",
477 .pm = &bcm63xx_spi_pm_ops, 627 .pm = &bcm63xx_spi_pm_ops,
478 }, 628 },
629 .id_table = bcm63xx_spi_dev_match,
479 .probe = bcm63xx_spi_probe, 630 .probe = bcm63xx_spi_probe,
480 .remove = bcm63xx_spi_remove, 631 .remove = bcm63xx_spi_remove,
481}; 632};