diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/ata/pata_octeon_cf.c | 423 | ||||
-rw-r--r-- | drivers/bcma/Kconfig | 9 | ||||
-rw-r--r-- | drivers/bcma/Makefile | 1 | ||||
-rw-r--r-- | drivers/bcma/bcma_private.h | 10 | ||||
-rw-r--r-- | drivers/bcma/driver_chipcommon.c | 81 | ||||
-rw-r--r-- | drivers/bcma/driver_gpio.c | 98 | ||||
-rw-r--r-- | drivers/bcma/main.c | 5 | ||||
-rw-r--r-- | drivers/edac/Kconfig | 33 | ||||
-rw-r--r-- | drivers/edac/Makefile | 5 | ||||
-rw-r--r-- | drivers/edac/octeon_edac-l2c.c | 208 | ||||
-rw-r--r-- | drivers/edac/octeon_edac-lmc.c | 186 | ||||
-rw-r--r-- | drivers/edac/octeon_edac-pc.c | 143 | ||||
-rw-r--r-- | drivers/edac/octeon_edac-pci.c | 111 | ||||
-rw-r--r-- | drivers/ssb/Kconfig | 9 | ||||
-rw-r--r-- | drivers/ssb/Makefile | 1 | ||||
-rw-r--r-- | drivers/ssb/driver_chipcommon.c | 78 | ||||
-rw-r--r-- | drivers/ssb/driver_extif.c | 43 | ||||
-rw-r--r-- | drivers/ssb/driver_gpio.c | 176 | ||||
-rw-r--r-- | drivers/ssb/main.c | 7 | ||||
-rw-r--r-- | drivers/ssb/ssb_private.h | 17 | ||||
-rw-r--r-- | drivers/video/console/newport_con.c | 11 |
21 files changed, 1503 insertions, 152 deletions
diff --git a/drivers/ata/pata_octeon_cf.c b/drivers/ata/pata_octeon_cf.c index 1d61d5d278fa..4e1194b4c271 100644 --- a/drivers/ata/pata_octeon_cf.c +++ b/drivers/ata/pata_octeon_cf.c | |||
@@ -5,19 +5,22 @@ | |||
5 | * License. See the file "COPYING" in the main directory of this archive | 5 | * License. See the file "COPYING" in the main directory of this archive |
6 | * for more details. | 6 | * for more details. |
7 | * | 7 | * |
8 | * Copyright (C) 2005 - 2009 Cavium Networks | 8 | * Copyright (C) 2005 - 2012 Cavium Inc. |
9 | * Copyright (C) 2008 Wind River Systems | 9 | * Copyright (C) 2008 Wind River Systems |
10 | */ | 10 | */ |
11 | 11 | ||
12 | #include <linux/kernel.h> | 12 | #include <linux/kernel.h> |
13 | #include <linux/module.h> | 13 | #include <linux/module.h> |
14 | #include <linux/libata.h> | 14 | #include <linux/libata.h> |
15 | #include <linux/irq.h> | 15 | #include <linux/hrtimer.h> |
16 | #include <linux/slab.h> | 16 | #include <linux/slab.h> |
17 | #include <linux/irq.h> | ||
18 | #include <linux/of.h> | ||
19 | #include <linux/of_platform.h> | ||
17 | #include <linux/platform_device.h> | 20 | #include <linux/platform_device.h> |
18 | #include <linux/workqueue.h> | ||
19 | #include <scsi/scsi_host.h> | 21 | #include <scsi/scsi_host.h> |
20 | 22 | ||
23 | #include <asm/byteorder.h> | ||
21 | #include <asm/octeon/octeon.h> | 24 | #include <asm/octeon/octeon.h> |
22 | 25 | ||
23 | /* | 26 | /* |
@@ -34,20 +37,36 @@ | |||
34 | */ | 37 | */ |
35 | 38 | ||
36 | #define DRV_NAME "pata_octeon_cf" | 39 | #define DRV_NAME "pata_octeon_cf" |
37 | #define DRV_VERSION "2.1" | 40 | #define DRV_VERSION "2.2" |
41 | |||
42 | /* Poll interval in nS. */ | ||
43 | #define OCTEON_CF_BUSY_POLL_INTERVAL 500000 | ||
38 | 44 | ||
45 | #define DMA_CFG 0 | ||
46 | #define DMA_TIM 0x20 | ||
47 | #define DMA_INT 0x38 | ||
48 | #define DMA_INT_EN 0x50 | ||
39 | 49 | ||
40 | struct octeon_cf_port { | 50 | struct octeon_cf_port { |
41 | struct workqueue_struct *wq; | 51 | struct hrtimer delayed_finish; |
42 | struct delayed_work delayed_finish; | ||
43 | struct ata_port *ap; | 52 | struct ata_port *ap; |
44 | int dma_finished; | 53 | int dma_finished; |
54 | void *c0; | ||
55 | unsigned int cs0; | ||
56 | unsigned int cs1; | ||
57 | bool is_true_ide; | ||
58 | u64 dma_base; | ||
45 | }; | 59 | }; |
46 | 60 | ||
47 | static struct scsi_host_template octeon_cf_sht = { | 61 | static struct scsi_host_template octeon_cf_sht = { |
48 | ATA_PIO_SHT(DRV_NAME), | 62 | ATA_PIO_SHT(DRV_NAME), |
49 | }; | 63 | }; |
50 | 64 | ||
65 | static int enable_dma; | ||
66 | module_param(enable_dma, int, 0444); | ||
67 | MODULE_PARM_DESC(enable_dma, | ||
68 | "Enable use of DMA on interfaces that support it (0=no dma [default], 1=use dma)"); | ||
69 | |||
51 | /** | 70 | /** |
52 | * Convert nanosecond based time to setting used in the | 71 | * Convert nanosecond based time to setting used in the |
53 | * boot bus timing register, based on timing multiple | 72 | * boot bus timing register, based on timing multiple |
@@ -66,12 +85,29 @@ static unsigned int ns_to_tim_reg(unsigned int tim_mult, unsigned int nsecs) | |||
66 | return val; | 85 | return val; |
67 | } | 86 | } |
68 | 87 | ||
69 | static void octeon_cf_set_boot_reg_cfg(int cs) | 88 | static void octeon_cf_set_boot_reg_cfg(int cs, unsigned int multiplier) |
70 | { | 89 | { |
71 | union cvmx_mio_boot_reg_cfgx reg_cfg; | 90 | union cvmx_mio_boot_reg_cfgx reg_cfg; |
91 | unsigned int tim_mult; | ||
92 | |||
93 | switch (multiplier) { | ||
94 | case 8: | ||
95 | tim_mult = 3; | ||
96 | break; | ||
97 | case 4: | ||
98 | tim_mult = 0; | ||
99 | break; | ||
100 | case 2: | ||
101 | tim_mult = 2; | ||
102 | break; | ||
103 | default: | ||
104 | tim_mult = 1; | ||
105 | break; | ||
106 | } | ||
107 | |||
72 | reg_cfg.u64 = cvmx_read_csr(CVMX_MIO_BOOT_REG_CFGX(cs)); | 108 | reg_cfg.u64 = cvmx_read_csr(CVMX_MIO_BOOT_REG_CFGX(cs)); |
73 | reg_cfg.s.dmack = 0; /* Don't assert DMACK on access */ | 109 | reg_cfg.s.dmack = 0; /* Don't assert DMACK on access */ |
74 | reg_cfg.s.tim_mult = 2; /* Timing mutiplier 2x */ | 110 | reg_cfg.s.tim_mult = tim_mult; /* Timing mutiplier */ |
75 | reg_cfg.s.rd_dly = 0; /* Sample on falling edge of BOOT_OE */ | 111 | reg_cfg.s.rd_dly = 0; /* Sample on falling edge of BOOT_OE */ |
76 | reg_cfg.s.sam = 0; /* Don't combine write and output enable */ | 112 | reg_cfg.s.sam = 0; /* Don't combine write and output enable */ |
77 | reg_cfg.s.we_ext = 0; /* No write enable extension */ | 113 | reg_cfg.s.we_ext = 0; /* No write enable extension */ |
@@ -92,12 +128,12 @@ static void octeon_cf_set_boot_reg_cfg(int cs) | |||
92 | */ | 128 | */ |
93 | static void octeon_cf_set_piomode(struct ata_port *ap, struct ata_device *dev) | 129 | static void octeon_cf_set_piomode(struct ata_port *ap, struct ata_device *dev) |
94 | { | 130 | { |
95 | struct octeon_cf_data *ocd = ap->dev->platform_data; | 131 | struct octeon_cf_port *cf_port = ap->private_data; |
96 | union cvmx_mio_boot_reg_timx reg_tim; | 132 | union cvmx_mio_boot_reg_timx reg_tim; |
97 | int cs = ocd->base_region; | ||
98 | int T; | 133 | int T; |
99 | struct ata_timing timing; | 134 | struct ata_timing timing; |
100 | 135 | ||
136 | unsigned int div; | ||
101 | int use_iordy; | 137 | int use_iordy; |
102 | int trh; | 138 | int trh; |
103 | int pause; | 139 | int pause; |
@@ -106,7 +142,15 @@ static void octeon_cf_set_piomode(struct ata_port *ap, struct ata_device *dev) | |||
106 | int t2; | 142 | int t2; |
107 | int t2i; | 143 | int t2i; |
108 | 144 | ||
109 | T = (int)(2000000000000LL / octeon_get_clock_rate()); | 145 | /* |
146 | * A divisor value of four will overflow the timing fields at | ||
147 | * clock rates greater than 800MHz | ||
148 | */ | ||
149 | if (octeon_get_io_clock_rate() <= 800000000) | ||
150 | div = 4; | ||
151 | else | ||
152 | div = 8; | ||
153 | T = (int)((1000000000000LL * div) / octeon_get_io_clock_rate()); | ||
110 | 154 | ||
111 | if (ata_timing_compute(dev, dev->pio_mode, &timing, T, T)) | 155 | if (ata_timing_compute(dev, dev->pio_mode, &timing, T, T)) |
112 | BUG(); | 156 | BUG(); |
@@ -121,23 +165,26 @@ static void octeon_cf_set_piomode(struct ata_port *ap, struct ata_device *dev) | |||
121 | if (t2i) | 165 | if (t2i) |
122 | t2i--; | 166 | t2i--; |
123 | 167 | ||
124 | trh = ns_to_tim_reg(2, 20); | 168 | trh = ns_to_tim_reg(div, 20); |
125 | if (trh) | 169 | if (trh) |
126 | trh--; | 170 | trh--; |
127 | 171 | ||
128 | pause = timing.cycle - timing.active - timing.setup - trh; | 172 | pause = (int)timing.cycle - (int)timing.active - |
173 | (int)timing.setup - trh; | ||
174 | if (pause < 0) | ||
175 | pause = 0; | ||
129 | if (pause) | 176 | if (pause) |
130 | pause--; | 177 | pause--; |
131 | 178 | ||
132 | octeon_cf_set_boot_reg_cfg(cs); | 179 | octeon_cf_set_boot_reg_cfg(cf_port->cs0, div); |
133 | if (ocd->dma_engine >= 0) | 180 | if (cf_port->is_true_ide) |
134 | /* True IDE mode, program both chip selects. */ | 181 | /* True IDE mode, program both chip selects. */ |
135 | octeon_cf_set_boot_reg_cfg(cs + 1); | 182 | octeon_cf_set_boot_reg_cfg(cf_port->cs1, div); |
136 | 183 | ||
137 | 184 | ||
138 | use_iordy = ata_pio_need_iordy(dev); | 185 | use_iordy = ata_pio_need_iordy(dev); |
139 | 186 | ||
140 | reg_tim.u64 = cvmx_read_csr(CVMX_MIO_BOOT_REG_TIMX(cs)); | 187 | reg_tim.u64 = cvmx_read_csr(CVMX_MIO_BOOT_REG_TIMX(cf_port->cs0)); |
141 | /* Disable page mode */ | 188 | /* Disable page mode */ |
142 | reg_tim.s.pagem = 0; | 189 | reg_tim.s.pagem = 0; |
143 | /* Enable dynamic timing */ | 190 | /* Enable dynamic timing */ |
@@ -161,20 +208,22 @@ static void octeon_cf_set_piomode(struct ata_port *ap, struct ata_device *dev) | |||
161 | /* How long read enable is asserted */ | 208 | /* How long read enable is asserted */ |
162 | reg_tim.s.oe = t2; | 209 | reg_tim.s.oe = t2; |
163 | /* Time after CE that read/write starts */ | 210 | /* Time after CE that read/write starts */ |
164 | reg_tim.s.ce = ns_to_tim_reg(2, 5); | 211 | reg_tim.s.ce = ns_to_tim_reg(div, 5); |
165 | /* Time before CE that address is valid */ | 212 | /* Time before CE that address is valid */ |
166 | reg_tim.s.adr = 0; | 213 | reg_tim.s.adr = 0; |
167 | 214 | ||
168 | /* Program the bootbus region timing for the data port chip select. */ | 215 | /* Program the bootbus region timing for the data port chip select. */ |
169 | cvmx_write_csr(CVMX_MIO_BOOT_REG_TIMX(cs), reg_tim.u64); | 216 | cvmx_write_csr(CVMX_MIO_BOOT_REG_TIMX(cf_port->cs0), reg_tim.u64); |
170 | if (ocd->dma_engine >= 0) | 217 | if (cf_port->is_true_ide) |
171 | /* True IDE mode, program both chip selects. */ | 218 | /* True IDE mode, program both chip selects. */ |
172 | cvmx_write_csr(CVMX_MIO_BOOT_REG_TIMX(cs + 1), reg_tim.u64); | 219 | cvmx_write_csr(CVMX_MIO_BOOT_REG_TIMX(cf_port->cs1), |
220 | reg_tim.u64); | ||
173 | } | 221 | } |
174 | 222 | ||
175 | static void octeon_cf_set_dmamode(struct ata_port *ap, struct ata_device *dev) | 223 | static void octeon_cf_set_dmamode(struct ata_port *ap, struct ata_device *dev) |
176 | { | 224 | { |
177 | struct octeon_cf_data *ocd = dev->link->ap->dev->platform_data; | 225 | struct octeon_cf_port *cf_port = ap->private_data; |
226 | union cvmx_mio_boot_pin_defs pin_defs; | ||
178 | union cvmx_mio_boot_dma_timx dma_tim; | 227 | union cvmx_mio_boot_dma_timx dma_tim; |
179 | unsigned int oe_a; | 228 | unsigned int oe_a; |
180 | unsigned int oe_n; | 229 | unsigned int oe_n; |
@@ -183,6 +232,7 @@ static void octeon_cf_set_dmamode(struct ata_port *ap, struct ata_device *dev) | |||
183 | unsigned int pause; | 232 | unsigned int pause; |
184 | unsigned int T0, Tkr, Td; | 233 | unsigned int T0, Tkr, Td; |
185 | unsigned int tim_mult; | 234 | unsigned int tim_mult; |
235 | int c; | ||
186 | 236 | ||
187 | const struct ata_timing *timing; | 237 | const struct ata_timing *timing; |
188 | 238 | ||
@@ -199,13 +249,19 @@ static void octeon_cf_set_dmamode(struct ata_port *ap, struct ata_device *dev) | |||
199 | /* not spec'ed, value in eclocks, not affected by tim_mult */ | 249 | /* not spec'ed, value in eclocks, not affected by tim_mult */ |
200 | dma_arq = 8; | 250 | dma_arq = 8; |
201 | pause = 25 - dma_arq * 1000 / | 251 | pause = 25 - dma_arq * 1000 / |
202 | (octeon_get_clock_rate() / 1000000); /* Tz */ | 252 | (octeon_get_io_clock_rate() / 1000000); /* Tz */ |
203 | 253 | ||
204 | oe_a = Td; | 254 | oe_a = Td; |
205 | /* Tkr from cf spec, lengthened to meet T0 */ | 255 | /* Tkr from cf spec, lengthened to meet T0 */ |
206 | oe_n = max(T0 - oe_a, Tkr); | 256 | oe_n = max(T0 - oe_a, Tkr); |
207 | 257 | ||
208 | dma_tim.s.dmack_pi = 1; | 258 | pin_defs.u64 = cvmx_read_csr(CVMX_MIO_BOOT_PIN_DEFS); |
259 | |||
260 | /* DMA channel number. */ | ||
261 | c = (cf_port->dma_base & 8) >> 3; | ||
262 | |||
263 | /* Invert the polarity if the default is 0*/ | ||
264 | dma_tim.s.dmack_pi = (pin_defs.u64 & (1ull << (11 + c))) ? 0 : 1; | ||
209 | 265 | ||
210 | dma_tim.s.oe_n = ns_to_tim_reg(tim_mult, oe_n); | 266 | dma_tim.s.oe_n = ns_to_tim_reg(tim_mult, oe_n); |
211 | dma_tim.s.oe_a = ns_to_tim_reg(tim_mult, oe_a); | 267 | dma_tim.s.oe_a = ns_to_tim_reg(tim_mult, oe_a); |
@@ -228,14 +284,11 @@ static void octeon_cf_set_dmamode(struct ata_port *ap, struct ata_device *dev) | |||
228 | 284 | ||
229 | pr_debug("ns to ticks (mult %d) of %d is: %d\n", tim_mult, 60, | 285 | pr_debug("ns to ticks (mult %d) of %d is: %d\n", tim_mult, 60, |
230 | ns_to_tim_reg(tim_mult, 60)); | 286 | ns_to_tim_reg(tim_mult, 60)); |
231 | pr_debug("oe_n: %d, oe_a: %d, dmack_s: %d, dmack_h: " | 287 | pr_debug("oe_n: %d, oe_a: %d, dmack_s: %d, dmack_h: %d, dmarq: %d, pause: %d\n", |
232 | "%d, dmarq: %d, pause: %d\n", | ||
233 | dma_tim.s.oe_n, dma_tim.s.oe_a, dma_tim.s.dmack_s, | 288 | dma_tim.s.oe_n, dma_tim.s.oe_a, dma_tim.s.dmack_s, |
234 | dma_tim.s.dmack_h, dma_tim.s.dmarq, dma_tim.s.pause); | 289 | dma_tim.s.dmack_h, dma_tim.s.dmarq, dma_tim.s.pause); |
235 | 290 | ||
236 | cvmx_write_csr(CVMX_MIO_BOOT_DMA_TIMX(ocd->dma_engine), | 291 | cvmx_write_csr(cf_port->dma_base + DMA_TIM, dma_tim.u64); |
237 | dma_tim.u64); | ||
238 | |||
239 | } | 292 | } |
240 | 293 | ||
241 | /** | 294 | /** |
@@ -489,15 +542,10 @@ static void octeon_cf_exec_command16(struct ata_port *ap, | |||
489 | ata_wait_idle(ap); | 542 | ata_wait_idle(ap); |
490 | } | 543 | } |
491 | 544 | ||
492 | static void octeon_cf_irq_on(struct ata_port *ap) | 545 | static void octeon_cf_ata_port_noaction(struct ata_port *ap) |
493 | { | 546 | { |
494 | } | 547 | } |
495 | 548 | ||
496 | static void octeon_cf_irq_clear(struct ata_port *ap) | ||
497 | { | ||
498 | return; | ||
499 | } | ||
500 | |||
501 | static void octeon_cf_dma_setup(struct ata_queued_cmd *qc) | 549 | static void octeon_cf_dma_setup(struct ata_queued_cmd *qc) |
502 | { | 550 | { |
503 | struct ata_port *ap = qc->ap; | 551 | struct ata_port *ap = qc->ap; |
@@ -519,7 +567,7 @@ static void octeon_cf_dma_setup(struct ata_queued_cmd *qc) | |||
519 | */ | 567 | */ |
520 | static void octeon_cf_dma_start(struct ata_queued_cmd *qc) | 568 | static void octeon_cf_dma_start(struct ata_queued_cmd *qc) |
521 | { | 569 | { |
522 | struct octeon_cf_data *ocd = qc->ap->dev->platform_data; | 570 | struct octeon_cf_port *cf_port = qc->ap->private_data; |
523 | union cvmx_mio_boot_dma_cfgx mio_boot_dma_cfg; | 571 | union cvmx_mio_boot_dma_cfgx mio_boot_dma_cfg; |
524 | union cvmx_mio_boot_dma_intx mio_boot_dma_int; | 572 | union cvmx_mio_boot_dma_intx mio_boot_dma_int; |
525 | struct scatterlist *sg; | 573 | struct scatterlist *sg; |
@@ -535,15 +583,16 @@ static void octeon_cf_dma_start(struct ata_queued_cmd *qc) | |||
535 | */ | 583 | */ |
536 | mio_boot_dma_int.u64 = 0; | 584 | mio_boot_dma_int.u64 = 0; |
537 | mio_boot_dma_int.s.done = 1; | 585 | mio_boot_dma_int.s.done = 1; |
538 | cvmx_write_csr(CVMX_MIO_BOOT_DMA_INTX(ocd->dma_engine), | 586 | cvmx_write_csr(cf_port->dma_base + DMA_INT, mio_boot_dma_int.u64); |
539 | mio_boot_dma_int.u64); | ||
540 | 587 | ||
541 | /* Enable the interrupt. */ | 588 | /* Enable the interrupt. */ |
542 | cvmx_write_csr(CVMX_MIO_BOOT_DMA_INT_ENX(ocd->dma_engine), | 589 | cvmx_write_csr(cf_port->dma_base + DMA_INT_EN, mio_boot_dma_int.u64); |
543 | mio_boot_dma_int.u64); | ||
544 | 590 | ||
545 | /* Set the direction of the DMA */ | 591 | /* Set the direction of the DMA */ |
546 | mio_boot_dma_cfg.u64 = 0; | 592 | mio_boot_dma_cfg.u64 = 0; |
593 | #ifdef __LITTLE_ENDIAN | ||
594 | mio_boot_dma_cfg.s.endian = 1; | ||
595 | #endif | ||
547 | mio_boot_dma_cfg.s.en = 1; | 596 | mio_boot_dma_cfg.s.en = 1; |
548 | mio_boot_dma_cfg.s.rw = ((qc->tf.flags & ATA_TFLAG_WRITE) != 0); | 597 | mio_boot_dma_cfg.s.rw = ((qc->tf.flags & ATA_TFLAG_WRITE) != 0); |
549 | 598 | ||
@@ -569,8 +618,7 @@ static void octeon_cf_dma_start(struct ata_queued_cmd *qc) | |||
569 | (mio_boot_dma_cfg.s.rw) ? "write" : "read", sg->length, | 618 | (mio_boot_dma_cfg.s.rw) ? "write" : "read", sg->length, |
570 | (void *)(unsigned long)mio_boot_dma_cfg.s.adr); | 619 | (void *)(unsigned long)mio_boot_dma_cfg.s.adr); |
571 | 620 | ||
572 | cvmx_write_csr(CVMX_MIO_BOOT_DMA_CFGX(ocd->dma_engine), | 621 | cvmx_write_csr(cf_port->dma_base + DMA_CFG, mio_boot_dma_cfg.u64); |
573 | mio_boot_dma_cfg.u64); | ||
574 | } | 622 | } |
575 | 623 | ||
576 | /** | 624 | /** |
@@ -583,10 +631,9 @@ static unsigned int octeon_cf_dma_finished(struct ata_port *ap, | |||
583 | struct ata_queued_cmd *qc) | 631 | struct ata_queued_cmd *qc) |
584 | { | 632 | { |
585 | struct ata_eh_info *ehi = &ap->link.eh_info; | 633 | struct ata_eh_info *ehi = &ap->link.eh_info; |
586 | struct octeon_cf_data *ocd = ap->dev->platform_data; | 634 | struct octeon_cf_port *cf_port = ap->private_data; |
587 | union cvmx_mio_boot_dma_cfgx dma_cfg; | 635 | union cvmx_mio_boot_dma_cfgx dma_cfg; |
588 | union cvmx_mio_boot_dma_intx dma_int; | 636 | union cvmx_mio_boot_dma_intx dma_int; |
589 | struct octeon_cf_port *cf_port; | ||
590 | u8 status; | 637 | u8 status; |
591 | 638 | ||
592 | VPRINTK("ata%u: protocol %d task_state %d\n", | 639 | VPRINTK("ata%u: protocol %d task_state %d\n", |
@@ -596,9 +643,7 @@ static unsigned int octeon_cf_dma_finished(struct ata_port *ap, | |||
596 | if (ap->hsm_task_state != HSM_ST_LAST) | 643 | if (ap->hsm_task_state != HSM_ST_LAST) |
597 | return 0; | 644 | return 0; |
598 | 645 | ||
599 | cf_port = ap->private_data; | 646 | dma_cfg.u64 = cvmx_read_csr(cf_port->dma_base + DMA_CFG); |
600 | |||
601 | dma_cfg.u64 = cvmx_read_csr(CVMX_MIO_BOOT_DMA_CFGX(ocd->dma_engine)); | ||
602 | if (dma_cfg.s.size != 0xfffff) { | 647 | if (dma_cfg.s.size != 0xfffff) { |
603 | /* Error, the transfer was not complete. */ | 648 | /* Error, the transfer was not complete. */ |
604 | qc->err_mask |= AC_ERR_HOST_BUS; | 649 | qc->err_mask |= AC_ERR_HOST_BUS; |
@@ -608,15 +653,15 @@ static unsigned int octeon_cf_dma_finished(struct ata_port *ap, | |||
608 | /* Stop and clear the dma engine. */ | 653 | /* Stop and clear the dma engine. */ |
609 | dma_cfg.u64 = 0; | 654 | dma_cfg.u64 = 0; |
610 | dma_cfg.s.size = -1; | 655 | dma_cfg.s.size = -1; |
611 | cvmx_write_csr(CVMX_MIO_BOOT_DMA_CFGX(ocd->dma_engine), dma_cfg.u64); | 656 | cvmx_write_csr(cf_port->dma_base + DMA_CFG, dma_cfg.u64); |
612 | 657 | ||
613 | /* Disable the interrupt. */ | 658 | /* Disable the interrupt. */ |
614 | dma_int.u64 = 0; | 659 | dma_int.u64 = 0; |
615 | cvmx_write_csr(CVMX_MIO_BOOT_DMA_INT_ENX(ocd->dma_engine), dma_int.u64); | 660 | cvmx_write_csr(cf_port->dma_base + DMA_INT_EN, dma_int.u64); |
616 | 661 | ||
617 | /* Clear the DMA complete status */ | 662 | /* Clear the DMA complete status */ |
618 | dma_int.s.done = 1; | 663 | dma_int.s.done = 1; |
619 | cvmx_write_csr(CVMX_MIO_BOOT_DMA_INTX(ocd->dma_engine), dma_int.u64); | 664 | cvmx_write_csr(cf_port->dma_base + DMA_INT, dma_int.u64); |
620 | 665 | ||
621 | status = ap->ops->sff_check_status(ap); | 666 | status = ap->ops->sff_check_status(ap); |
622 | 667 | ||
@@ -649,69 +694,68 @@ static irqreturn_t octeon_cf_interrupt(int irq, void *dev_instance) | |||
649 | struct ata_queued_cmd *qc; | 694 | struct ata_queued_cmd *qc; |
650 | union cvmx_mio_boot_dma_intx dma_int; | 695 | union cvmx_mio_boot_dma_intx dma_int; |
651 | union cvmx_mio_boot_dma_cfgx dma_cfg; | 696 | union cvmx_mio_boot_dma_cfgx dma_cfg; |
652 | struct octeon_cf_data *ocd; | ||
653 | 697 | ||
654 | ap = host->ports[i]; | 698 | ap = host->ports[i]; |
655 | ocd = ap->dev->platform_data; | ||
656 | cf_port = ap->private_data; | 699 | cf_port = ap->private_data; |
657 | dma_int.u64 = | 700 | |
658 | cvmx_read_csr(CVMX_MIO_BOOT_DMA_INTX(ocd->dma_engine)); | 701 | dma_int.u64 = cvmx_read_csr(cf_port->dma_base + DMA_INT); |
659 | dma_cfg.u64 = | 702 | dma_cfg.u64 = cvmx_read_csr(cf_port->dma_base + DMA_CFG); |
660 | cvmx_read_csr(CVMX_MIO_BOOT_DMA_CFGX(ocd->dma_engine)); | ||
661 | 703 | ||
662 | qc = ata_qc_from_tag(ap, ap->link.active_tag); | 704 | qc = ata_qc_from_tag(ap, ap->link.active_tag); |
663 | 705 | ||
664 | if (qc && !(qc->tf.flags & ATA_TFLAG_POLLING)) { | 706 | if (!qc || (qc->tf.flags & ATA_TFLAG_POLLING)) |
665 | if (dma_int.s.done && !dma_cfg.s.en) { | 707 | continue; |
666 | if (!sg_is_last(qc->cursg)) { | 708 | |
667 | qc->cursg = sg_next(qc->cursg); | 709 | if (dma_int.s.done && !dma_cfg.s.en) { |
668 | handled = 1; | 710 | if (!sg_is_last(qc->cursg)) { |
669 | octeon_cf_dma_start(qc); | 711 | qc->cursg = sg_next(qc->cursg); |
670 | continue; | ||
671 | } else { | ||
672 | cf_port->dma_finished = 1; | ||
673 | } | ||
674 | } | ||
675 | if (!cf_port->dma_finished) | ||
676 | continue; | ||
677 | status = ioread8(ap->ioaddr.altstatus_addr); | ||
678 | if (status & (ATA_BUSY | ATA_DRQ)) { | ||
679 | /* | ||
680 | * We are busy, try to handle it | ||
681 | * later. This is the DMA finished | ||
682 | * interrupt, and it could take a | ||
683 | * little while for the card to be | ||
684 | * ready for more commands. | ||
685 | */ | ||
686 | /* Clear DMA irq. */ | ||
687 | dma_int.u64 = 0; | ||
688 | dma_int.s.done = 1; | ||
689 | cvmx_write_csr(CVMX_MIO_BOOT_DMA_INTX(ocd->dma_engine), | ||
690 | dma_int.u64); | ||
691 | |||
692 | queue_delayed_work(cf_port->wq, | ||
693 | &cf_port->delayed_finish, 1); | ||
694 | handled = 1; | 712 | handled = 1; |
713 | octeon_cf_dma_start(qc); | ||
714 | continue; | ||
695 | } else { | 715 | } else { |
696 | handled |= octeon_cf_dma_finished(ap, qc); | 716 | cf_port->dma_finished = 1; |
697 | } | 717 | } |
698 | } | 718 | } |
719 | if (!cf_port->dma_finished) | ||
720 | continue; | ||
721 | status = ioread8(ap->ioaddr.altstatus_addr); | ||
722 | if (status & (ATA_BUSY | ATA_DRQ)) { | ||
723 | /* | ||
724 | * We are busy, try to handle it later. This | ||
725 | * is the DMA finished interrupt, and it could | ||
726 | * take a little while for the card to be | ||
727 | * ready for more commands. | ||
728 | */ | ||
729 | /* Clear DMA irq. */ | ||
730 | dma_int.u64 = 0; | ||
731 | dma_int.s.done = 1; | ||
732 | cvmx_write_csr(cf_port->dma_base + DMA_INT, | ||
733 | dma_int.u64); | ||
734 | hrtimer_start_range_ns(&cf_port->delayed_finish, | ||
735 | ns_to_ktime(OCTEON_CF_BUSY_POLL_INTERVAL), | ||
736 | OCTEON_CF_BUSY_POLL_INTERVAL / 5, | ||
737 | HRTIMER_MODE_REL); | ||
738 | handled = 1; | ||
739 | } else { | ||
740 | handled |= octeon_cf_dma_finished(ap, qc); | ||
741 | } | ||
699 | } | 742 | } |
700 | spin_unlock_irqrestore(&host->lock, flags); | 743 | spin_unlock_irqrestore(&host->lock, flags); |
701 | DPRINTK("EXIT\n"); | 744 | DPRINTK("EXIT\n"); |
702 | return IRQ_RETVAL(handled); | 745 | return IRQ_RETVAL(handled); |
703 | } | 746 | } |
704 | 747 | ||
705 | static void octeon_cf_delayed_finish(struct work_struct *work) | 748 | static enum hrtimer_restart octeon_cf_delayed_finish(struct hrtimer *hrt) |
706 | { | 749 | { |
707 | struct octeon_cf_port *cf_port = container_of(work, | 750 | struct octeon_cf_port *cf_port = container_of(hrt, |
708 | struct octeon_cf_port, | 751 | struct octeon_cf_port, |
709 | delayed_finish.work); | 752 | delayed_finish); |
710 | struct ata_port *ap = cf_port->ap; | 753 | struct ata_port *ap = cf_port->ap; |
711 | struct ata_host *host = ap->host; | 754 | struct ata_host *host = ap->host; |
712 | struct ata_queued_cmd *qc; | 755 | struct ata_queued_cmd *qc; |
713 | unsigned long flags; | 756 | unsigned long flags; |
714 | u8 status; | 757 | u8 status; |
758 | enum hrtimer_restart rv = HRTIMER_NORESTART; | ||
715 | 759 | ||
716 | spin_lock_irqsave(&host->lock, flags); | 760 | spin_lock_irqsave(&host->lock, flags); |
717 | 761 | ||
@@ -726,15 +770,17 @@ static void octeon_cf_delayed_finish(struct work_struct *work) | |||
726 | status = ioread8(ap->ioaddr.altstatus_addr); | 770 | status = ioread8(ap->ioaddr.altstatus_addr); |
727 | if (status & (ATA_BUSY | ATA_DRQ)) { | 771 | if (status & (ATA_BUSY | ATA_DRQ)) { |
728 | /* Still busy, try again. */ | 772 | /* Still busy, try again. */ |
729 | queue_delayed_work(cf_port->wq, | 773 | hrtimer_forward_now(hrt, |
730 | &cf_port->delayed_finish, 1); | 774 | ns_to_ktime(OCTEON_CF_BUSY_POLL_INTERVAL)); |
775 | rv = HRTIMER_RESTART; | ||
731 | goto out; | 776 | goto out; |
732 | } | 777 | } |
733 | qc = ata_qc_from_tag(ap, ap->link.active_tag); | 778 | qc = ata_qc_from_tag(ap, ap->link.active_tag); |
734 | if (qc && !(qc->tf.flags & ATA_TFLAG_POLLING)) | 779 | if (qc && (!(qc->tf.flags & ATA_TFLAG_POLLING))) |
735 | octeon_cf_dma_finished(ap, qc); | 780 | octeon_cf_dma_finished(ap, qc); |
736 | out: | 781 | out: |
737 | spin_unlock_irqrestore(&host->lock, flags); | 782 | spin_unlock_irqrestore(&host->lock, flags); |
783 | return rv; | ||
738 | } | 784 | } |
739 | 785 | ||
740 | static void octeon_cf_dev_config(struct ata_device *dev) | 786 | static void octeon_cf_dev_config(struct ata_device *dev) |
@@ -786,8 +832,8 @@ static struct ata_port_operations octeon_cf_ops = { | |||
786 | .qc_prep = ata_noop_qc_prep, | 832 | .qc_prep = ata_noop_qc_prep, |
787 | .qc_issue = octeon_cf_qc_issue, | 833 | .qc_issue = octeon_cf_qc_issue, |
788 | .sff_dev_select = octeon_cf_dev_select, | 834 | .sff_dev_select = octeon_cf_dev_select, |
789 | .sff_irq_on = octeon_cf_irq_on, | 835 | .sff_irq_on = octeon_cf_ata_port_noaction, |
790 | .sff_irq_clear = octeon_cf_irq_clear, | 836 | .sff_irq_clear = octeon_cf_ata_port_noaction, |
791 | .cable_detect = ata_cable_40wire, | 837 | .cable_detect = ata_cable_40wire, |
792 | .set_piomode = octeon_cf_set_piomode, | 838 | .set_piomode = octeon_cf_set_piomode, |
793 | .set_dmamode = octeon_cf_set_dmamode, | 839 | .set_dmamode = octeon_cf_set_dmamode, |
@@ -798,46 +844,113 @@ static int __devinit octeon_cf_probe(struct platform_device *pdev) | |||
798 | { | 844 | { |
799 | struct resource *res_cs0, *res_cs1; | 845 | struct resource *res_cs0, *res_cs1; |
800 | 846 | ||
847 | bool is_16bit; | ||
848 | const __be32 *cs_num; | ||
849 | struct property *reg_prop; | ||
850 | int n_addr, n_size, reg_len; | ||
851 | struct device_node *node; | ||
852 | const void *prop; | ||
801 | void __iomem *cs0; | 853 | void __iomem *cs0; |
802 | void __iomem *cs1 = NULL; | 854 | void __iomem *cs1 = NULL; |
803 | struct ata_host *host; | 855 | struct ata_host *host; |
804 | struct ata_port *ap; | 856 | struct ata_port *ap; |
805 | struct octeon_cf_data *ocd; | ||
806 | int irq = 0; | 857 | int irq = 0; |
807 | irq_handler_t irq_handler = NULL; | 858 | irq_handler_t irq_handler = NULL; |
808 | void __iomem *base; | 859 | void __iomem *base; |
809 | struct octeon_cf_port *cf_port; | 860 | struct octeon_cf_port *cf_port; |
810 | char version[32]; | 861 | int rv = -ENOMEM; |
811 | 862 | ||
812 | res_cs0 = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
813 | 863 | ||
814 | if (!res_cs0) | 864 | node = pdev->dev.of_node; |
865 | if (node == NULL) | ||
815 | return -EINVAL; | 866 | return -EINVAL; |
816 | 867 | ||
817 | ocd = pdev->dev.platform_data; | 868 | cf_port = kzalloc(sizeof(*cf_port), GFP_KERNEL); |
869 | if (!cf_port) | ||
870 | return -ENOMEM; | ||
818 | 871 | ||
819 | cs0 = devm_ioremap_nocache(&pdev->dev, res_cs0->start, | 872 | cf_port->is_true_ide = (of_find_property(node, "cavium,true-ide", NULL) != NULL); |
820 | resource_size(res_cs0)); | ||
821 | 873 | ||
822 | if (!cs0) | 874 | prop = of_get_property(node, "cavium,bus-width", NULL); |
823 | return -ENOMEM; | 875 | if (prop) |
876 | is_16bit = (be32_to_cpup(prop) == 16); | ||
877 | else | ||
878 | is_16bit = false; | ||
824 | 879 | ||
825 | /* Determine from availability of DMA if True IDE mode or not */ | 880 | n_addr = of_n_addr_cells(node); |
826 | if (ocd->dma_engine >= 0) { | 881 | n_size = of_n_size_cells(node); |
827 | res_cs1 = platform_get_resource(pdev, IORESOURCE_MEM, 1); | ||
828 | if (!res_cs1) | ||
829 | return -EINVAL; | ||
830 | 882 | ||
883 | reg_prop = of_find_property(node, "reg", ®_len); | ||
884 | if (!reg_prop || reg_len < sizeof(__be32)) { | ||
885 | rv = -EINVAL; | ||
886 | goto free_cf_port; | ||
887 | } | ||
888 | cs_num = reg_prop->value; | ||
889 | cf_port->cs0 = be32_to_cpup(cs_num); | ||
890 | |||
891 | if (cf_port->is_true_ide) { | ||
892 | struct device_node *dma_node; | ||
893 | dma_node = of_parse_phandle(node, | ||
894 | "cavium,dma-engine-handle", 0); | ||
895 | if (dma_node) { | ||
896 | struct platform_device *dma_dev; | ||
897 | dma_dev = of_find_device_by_node(dma_node); | ||
898 | if (dma_dev) { | ||
899 | struct resource *res_dma; | ||
900 | int i; | ||
901 | res_dma = platform_get_resource(dma_dev, IORESOURCE_MEM, 0); | ||
902 | if (!res_dma) { | ||
903 | of_node_put(dma_node); | ||
904 | rv = -EINVAL; | ||
905 | goto free_cf_port; | ||
906 | } | ||
907 | cf_port->dma_base = (u64)devm_ioremap_nocache(&pdev->dev, res_dma->start, | ||
908 | resource_size(res_dma)); | ||
909 | |||
910 | if (!cf_port->dma_base) { | ||
911 | of_node_put(dma_node); | ||
912 | rv = -EINVAL; | ||
913 | goto free_cf_port; | ||
914 | } | ||
915 | |||
916 | irq_handler = octeon_cf_interrupt; | ||
917 | i = platform_get_irq(dma_dev, 0); | ||
918 | if (i > 0) | ||
919 | irq = i; | ||
920 | } | ||
921 | of_node_put(dma_node); | ||
922 | } | ||
923 | res_cs1 = platform_get_resource(pdev, IORESOURCE_MEM, 1); | ||
924 | if (!res_cs1) { | ||
925 | rv = -EINVAL; | ||
926 | goto free_cf_port; | ||
927 | } | ||
831 | cs1 = devm_ioremap_nocache(&pdev->dev, res_cs1->start, | 928 | cs1 = devm_ioremap_nocache(&pdev->dev, res_cs1->start, |
832 | resource_size(res_cs1)); | 929 | res_cs1->end - res_cs1->start + 1); |
833 | 930 | ||
834 | if (!cs1) | 931 | if (!cs1) |
835 | return -ENOMEM; | 932 | goto free_cf_port; |
933 | |||
934 | if (reg_len < (n_addr + n_size + 1) * sizeof(__be32)) { | ||
935 | rv = -EINVAL; | ||
936 | goto free_cf_port; | ||
937 | } | ||
938 | cs_num += n_addr + n_size; | ||
939 | cf_port->cs1 = be32_to_cpup(cs_num); | ||
836 | } | 940 | } |
837 | 941 | ||
838 | cf_port = kzalloc(sizeof(*cf_port), GFP_KERNEL); | 942 | res_cs0 = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
839 | if (!cf_port) | 943 | |
840 | return -ENOMEM; | 944 | if (!res_cs0) { |
945 | rv = -EINVAL; | ||
946 | goto free_cf_port; | ||
947 | } | ||
948 | |||
949 | cs0 = devm_ioremap_nocache(&pdev->dev, res_cs0->start, | ||
950 | resource_size(res_cs0)); | ||
951 | |||
952 | if (!cs0) | ||
953 | goto free_cf_port; | ||
841 | 954 | ||
842 | /* allocate host */ | 955 | /* allocate host */ |
843 | host = ata_host_alloc(&pdev->dev, 1); | 956 | host = ata_host_alloc(&pdev->dev, 1); |
@@ -846,21 +959,22 @@ static int __devinit octeon_cf_probe(struct platform_device *pdev) | |||
846 | 959 | ||
847 | ap = host->ports[0]; | 960 | ap = host->ports[0]; |
848 | ap->private_data = cf_port; | 961 | ap->private_data = cf_port; |
962 | pdev->dev.platform_data = cf_port; | ||
849 | cf_port->ap = ap; | 963 | cf_port->ap = ap; |
850 | ap->ops = &octeon_cf_ops; | 964 | ap->ops = &octeon_cf_ops; |
851 | ap->pio_mask = ATA_PIO6; | 965 | ap->pio_mask = ATA_PIO6; |
852 | ap->flags |= ATA_FLAG_NO_ATAPI | ATA_FLAG_PIO_POLLING; | 966 | ap->flags |= ATA_FLAG_NO_ATAPI | ATA_FLAG_PIO_POLLING; |
853 | 967 | ||
854 | base = cs0 + ocd->base_region_bias; | 968 | if (!is_16bit) { |
855 | if (!ocd->is16bit) { | 969 | base = cs0 + 0x800; |
856 | ap->ioaddr.cmd_addr = base; | 970 | ap->ioaddr.cmd_addr = base; |
857 | ata_sff_std_ports(&ap->ioaddr); | 971 | ata_sff_std_ports(&ap->ioaddr); |
858 | 972 | ||
859 | ap->ioaddr.altstatus_addr = base + 0xe; | 973 | ap->ioaddr.altstatus_addr = base + 0xe; |
860 | ap->ioaddr.ctl_addr = base + 0xe; | 974 | ap->ioaddr.ctl_addr = base + 0xe; |
861 | octeon_cf_ops.sff_data_xfer = octeon_cf_data_xfer8; | 975 | octeon_cf_ops.sff_data_xfer = octeon_cf_data_xfer8; |
862 | } else if (cs1) { | 976 | } else if (cf_port->is_true_ide) { |
863 | /* Presence of cs1 indicates True IDE mode. */ | 977 | base = cs0; |
864 | ap->ioaddr.cmd_addr = base + (ATA_REG_CMD << 1) + 1; | 978 | ap->ioaddr.cmd_addr = base + (ATA_REG_CMD << 1) + 1; |
865 | ap->ioaddr.data_addr = base + (ATA_REG_DATA << 1); | 979 | ap->ioaddr.data_addr = base + (ATA_REG_DATA << 1); |
866 | ap->ioaddr.error_addr = base + (ATA_REG_ERR << 1) + 1; | 980 | ap->ioaddr.error_addr = base + (ATA_REG_ERR << 1) + 1; |
@@ -876,19 +990,15 @@ static int __devinit octeon_cf_probe(struct platform_device *pdev) | |||
876 | ap->ioaddr.ctl_addr = cs1 + (6 << 1) + 1; | 990 | ap->ioaddr.ctl_addr = cs1 + (6 << 1) + 1; |
877 | octeon_cf_ops.sff_data_xfer = octeon_cf_data_xfer16; | 991 | octeon_cf_ops.sff_data_xfer = octeon_cf_data_xfer16; |
878 | 992 | ||
879 | ap->mwdma_mask = ATA_MWDMA4; | 993 | ap->mwdma_mask = enable_dma ? ATA_MWDMA4 : 0; |
880 | irq = platform_get_irq(pdev, 0); | ||
881 | irq_handler = octeon_cf_interrupt; | ||
882 | |||
883 | /* True IDE mode needs delayed work to poll for not-busy. */ | ||
884 | cf_port->wq = create_singlethread_workqueue(DRV_NAME); | ||
885 | if (!cf_port->wq) | ||
886 | goto free_cf_port; | ||
887 | INIT_DELAYED_WORK(&cf_port->delayed_finish, | ||
888 | octeon_cf_delayed_finish); | ||
889 | 994 | ||
995 | /* True IDE mode needs a timer to poll for not-busy. */ | ||
996 | hrtimer_init(&cf_port->delayed_finish, CLOCK_MONOTONIC, | ||
997 | HRTIMER_MODE_REL); | ||
998 | cf_port->delayed_finish.function = octeon_cf_delayed_finish; | ||
890 | } else { | 999 | } else { |
891 | /* 16 bit but not True IDE */ | 1000 | /* 16 bit but not True IDE */ |
1001 | base = cs0 + 0x800; | ||
892 | octeon_cf_ops.sff_data_xfer = octeon_cf_data_xfer16; | 1002 | octeon_cf_ops.sff_data_xfer = octeon_cf_data_xfer16; |
893 | octeon_cf_ops.softreset = octeon_cf_softreset16; | 1003 | octeon_cf_ops.softreset = octeon_cf_softreset16; |
894 | octeon_cf_ops.sff_check_status = octeon_cf_check_status16; | 1004 | octeon_cf_ops.sff_check_status = octeon_cf_check_status16; |
@@ -902,28 +1012,71 @@ static int __devinit octeon_cf_probe(struct platform_device *pdev) | |||
902 | ap->ioaddr.ctl_addr = base + 0xe; | 1012 | ap->ioaddr.ctl_addr = base + 0xe; |
903 | ap->ioaddr.altstatus_addr = base + 0xe; | 1013 | ap->ioaddr.altstatus_addr = base + 0xe; |
904 | } | 1014 | } |
1015 | cf_port->c0 = ap->ioaddr.ctl_addr; | ||
1016 | |||
1017 | pdev->dev.coherent_dma_mask = DMA_BIT_MASK(64); | ||
1018 | pdev->dev.dma_mask = &pdev->dev.coherent_dma_mask; | ||
905 | 1019 | ||
906 | ata_port_desc(ap, "cmd %p ctl %p", base, ap->ioaddr.ctl_addr); | 1020 | ata_port_desc(ap, "cmd %p ctl %p", base, ap->ioaddr.ctl_addr); |
907 | 1021 | ||
908 | 1022 | ||
909 | snprintf(version, sizeof(version), "%s %d bit%s", | 1023 | dev_info(&pdev->dev, "version " DRV_VERSION" %d bit%s.\n", |
910 | DRV_VERSION, | 1024 | is_16bit ? 16 : 8, |
911 | (ocd->is16bit) ? 16 : 8, | 1025 | cf_port->is_true_ide ? ", True IDE" : ""); |
912 | (cs1) ? ", True IDE" : ""); | ||
913 | ata_print_version_once(&pdev->dev, version); | ||
914 | 1026 | ||
915 | return ata_host_activate(host, irq, irq_handler, 0, &octeon_cf_sht); | 1027 | return ata_host_activate(host, irq, irq_handler, |
1028 | IRQF_SHARED, &octeon_cf_sht); | ||
916 | 1029 | ||
917 | free_cf_port: | 1030 | free_cf_port: |
918 | kfree(cf_port); | 1031 | kfree(cf_port); |
919 | return -ENOMEM; | 1032 | return rv; |
1033 | } | ||
1034 | |||
1035 | static void octeon_cf_shutdown(struct device *dev) | ||
1036 | { | ||
1037 | union cvmx_mio_boot_dma_cfgx dma_cfg; | ||
1038 | union cvmx_mio_boot_dma_intx dma_int; | ||
1039 | |||
1040 | struct octeon_cf_port *cf_port = dev->platform_data; | ||
1041 | |||
1042 | if (cf_port->dma_base) { | ||
1043 | /* Stop and clear the dma engine. */ | ||
1044 | dma_cfg.u64 = 0; | ||
1045 | dma_cfg.s.size = -1; | ||
1046 | cvmx_write_csr(cf_port->dma_base + DMA_CFG, dma_cfg.u64); | ||
1047 | |||
1048 | /* Disable the interrupt. */ | ||
1049 | dma_int.u64 = 0; | ||
1050 | cvmx_write_csr(cf_port->dma_base + DMA_INT_EN, dma_int.u64); | ||
1051 | |||
1052 | /* Clear the DMA complete status */ | ||
1053 | dma_int.s.done = 1; | ||
1054 | cvmx_write_csr(cf_port->dma_base + DMA_INT, dma_int.u64); | ||
1055 | |||
1056 | __raw_writeb(0, cf_port->c0); | ||
1057 | udelay(20); | ||
1058 | __raw_writeb(ATA_SRST, cf_port->c0); | ||
1059 | udelay(20); | ||
1060 | __raw_writeb(0, cf_port->c0); | ||
1061 | mdelay(100); | ||
1062 | } | ||
920 | } | 1063 | } |
921 | 1064 | ||
1065 | static struct of_device_id octeon_cf_match[] = { | ||
1066 | { | ||
1067 | .compatible = "cavium,ebt3000-compact-flash", | ||
1068 | }, | ||
1069 | {}, | ||
1070 | }; | ||
1071 | MODULE_DEVICE_TABLE(of, octeon_i2c_match); | ||
1072 | |||
922 | static struct platform_driver octeon_cf_driver = { | 1073 | static struct platform_driver octeon_cf_driver = { |
923 | .probe = octeon_cf_probe, | 1074 | .probe = octeon_cf_probe, |
924 | .driver = { | 1075 | .driver = { |
925 | .name = DRV_NAME, | 1076 | .name = DRV_NAME, |
926 | .owner = THIS_MODULE, | 1077 | .owner = THIS_MODULE, |
1078 | .of_match_table = octeon_cf_match, | ||
1079 | .shutdown = octeon_cf_shutdown | ||
927 | }, | 1080 | }, |
928 | }; | 1081 | }; |
929 | 1082 | ||
diff --git a/drivers/bcma/Kconfig b/drivers/bcma/Kconfig index a533af218368..d7b56a88c9f4 100644 --- a/drivers/bcma/Kconfig +++ b/drivers/bcma/Kconfig | |||
@@ -65,6 +65,15 @@ config BCMA_DRIVER_GMAC_CMN | |||
65 | 65 | ||
66 | If unsure, say N | 66 | If unsure, say N |
67 | 67 | ||
68 | config BCMA_DRIVER_GPIO | ||
69 | bool "BCMA GPIO driver" | ||
70 | depends on BCMA | ||
71 | select GPIOLIB | ||
72 | help | ||
73 | Driver to provide access to the GPIO pins of the bcma bus. | ||
74 | |||
75 | If unsure, say N | ||
76 | |||
68 | config BCMA_DEBUG | 77 | config BCMA_DEBUG |
69 | bool "BCMA debugging" | 78 | bool "BCMA debugging" |
70 | depends on BCMA | 79 | depends on BCMA |
diff --git a/drivers/bcma/Makefile b/drivers/bcma/Makefile index 8ad42d41b2f2..734b32f09c0a 100644 --- a/drivers/bcma/Makefile +++ b/drivers/bcma/Makefile | |||
@@ -6,6 +6,7 @@ bcma-y += driver_pci.o | |||
6 | bcma-$(CONFIG_BCMA_DRIVER_PCI_HOSTMODE) += driver_pci_host.o | 6 | bcma-$(CONFIG_BCMA_DRIVER_PCI_HOSTMODE) += driver_pci_host.o |
7 | bcma-$(CONFIG_BCMA_DRIVER_MIPS) += driver_mips.o | 7 | bcma-$(CONFIG_BCMA_DRIVER_MIPS) += driver_mips.o |
8 | bcma-$(CONFIG_BCMA_DRIVER_GMAC_CMN) += driver_gmac_cmn.o | 8 | bcma-$(CONFIG_BCMA_DRIVER_GMAC_CMN) += driver_gmac_cmn.o |
9 | bcma-$(CONFIG_BCMA_DRIVER_GPIO) += driver_gpio.o | ||
9 | bcma-$(CONFIG_BCMA_HOST_PCI) += host_pci.o | 10 | bcma-$(CONFIG_BCMA_HOST_PCI) += host_pci.o |
10 | bcma-$(CONFIG_BCMA_HOST_SOC) += host_soc.o | 11 | bcma-$(CONFIG_BCMA_HOST_SOC) += host_soc.o |
11 | obj-$(CONFIG_BCMA) += bcma.o | 12 | obj-$(CONFIG_BCMA) += bcma.o |
diff --git a/drivers/bcma/bcma_private.h b/drivers/bcma/bcma_private.h index 537ae53231cd..4a2d72ec6d43 100644 --- a/drivers/bcma/bcma_private.h +++ b/drivers/bcma/bcma_private.h | |||
@@ -91,4 +91,14 @@ bool __devinit bcma_core_pci_is_in_hostmode(struct bcma_drv_pci *pc); | |||
91 | void __devinit bcma_core_pci_hostmode_init(struct bcma_drv_pci *pc); | 91 | void __devinit bcma_core_pci_hostmode_init(struct bcma_drv_pci *pc); |
92 | #endif /* CONFIG_BCMA_DRIVER_PCI_HOSTMODE */ | 92 | #endif /* CONFIG_BCMA_DRIVER_PCI_HOSTMODE */ |
93 | 93 | ||
94 | #ifdef CONFIG_BCMA_DRIVER_GPIO | ||
95 | /* driver_gpio.c */ | ||
96 | int bcma_gpio_init(struct bcma_drv_cc *cc); | ||
97 | #else | ||
98 | static inline int bcma_gpio_init(struct bcma_drv_cc *cc) | ||
99 | { | ||
100 | return -ENOTSUPP; | ||
101 | } | ||
102 | #endif /* CONFIG_BCMA_DRIVER_GPIO */ | ||
103 | |||
94 | #endif | 104 | #endif |
diff --git a/drivers/bcma/driver_chipcommon.c b/drivers/bcma/driver_chipcommon.c index dc96dd8ebff2..e461ad25fda4 100644 --- a/drivers/bcma/driver_chipcommon.c +++ b/drivers/bcma/driver_chipcommon.c | |||
@@ -114,6 +114,8 @@ void bcma_core_chipcommon_early_init(struct bcma_drv_cc *cc) | |||
114 | if (cc->early_setup_done) | 114 | if (cc->early_setup_done) |
115 | return; | 115 | return; |
116 | 116 | ||
117 | spin_lock_init(&cc->gpio_lock); | ||
118 | |||
117 | if (cc->core->id.rev >= 11) | 119 | if (cc->core->id.rev >= 11) |
118 | cc->status = bcma_cc_read32(cc, BCMA_CC_CHIPSTAT); | 120 | cc->status = bcma_cc_read32(cc, BCMA_CC_CHIPSTAT); |
119 | cc->capabilities = bcma_cc_read32(cc, BCMA_CC_CAP); | 121 | cc->capabilities = bcma_cc_read32(cc, BCMA_CC_CAP); |
@@ -202,28 +204,97 @@ u32 bcma_chipco_gpio_in(struct bcma_drv_cc *cc, u32 mask) | |||
202 | 204 | ||
203 | u32 bcma_chipco_gpio_out(struct bcma_drv_cc *cc, u32 mask, u32 value) | 205 | u32 bcma_chipco_gpio_out(struct bcma_drv_cc *cc, u32 mask, u32 value) |
204 | { | 206 | { |
205 | return bcma_cc_write32_masked(cc, BCMA_CC_GPIOOUT, mask, value); | 207 | unsigned long flags; |
208 | u32 res; | ||
209 | |||
210 | spin_lock_irqsave(&cc->gpio_lock, flags); | ||
211 | res = bcma_cc_write32_masked(cc, BCMA_CC_GPIOOUT, mask, value); | ||
212 | spin_unlock_irqrestore(&cc->gpio_lock, flags); | ||
213 | |||
214 | return res; | ||
206 | } | 215 | } |
207 | 216 | ||
208 | u32 bcma_chipco_gpio_outen(struct bcma_drv_cc *cc, u32 mask, u32 value) | 217 | u32 bcma_chipco_gpio_outen(struct bcma_drv_cc *cc, u32 mask, u32 value) |
209 | { | 218 | { |
210 | return bcma_cc_write32_masked(cc, BCMA_CC_GPIOOUTEN, mask, value); | 219 | unsigned long flags; |
220 | u32 res; | ||
221 | |||
222 | spin_lock_irqsave(&cc->gpio_lock, flags); | ||
223 | res = bcma_cc_write32_masked(cc, BCMA_CC_GPIOOUTEN, mask, value); | ||
224 | spin_unlock_irqrestore(&cc->gpio_lock, flags); | ||
225 | |||
226 | return res; | ||
211 | } | 227 | } |
212 | 228 | ||
229 | /* | ||
230 | * If the bit is set to 0, chipcommon controlls this GPIO, | ||
231 | * if the bit is set to 1, it is used by some part of the chip and not our code. | ||
232 | */ | ||
213 | u32 bcma_chipco_gpio_control(struct bcma_drv_cc *cc, u32 mask, u32 value) | 233 | u32 bcma_chipco_gpio_control(struct bcma_drv_cc *cc, u32 mask, u32 value) |
214 | { | 234 | { |
215 | return bcma_cc_write32_masked(cc, BCMA_CC_GPIOCTL, mask, value); | 235 | unsigned long flags; |
236 | u32 res; | ||
237 | |||
238 | spin_lock_irqsave(&cc->gpio_lock, flags); | ||
239 | res = bcma_cc_write32_masked(cc, BCMA_CC_GPIOCTL, mask, value); | ||
240 | spin_unlock_irqrestore(&cc->gpio_lock, flags); | ||
241 | |||
242 | return res; | ||
216 | } | 243 | } |
217 | EXPORT_SYMBOL_GPL(bcma_chipco_gpio_control); | 244 | EXPORT_SYMBOL_GPL(bcma_chipco_gpio_control); |
218 | 245 | ||
219 | u32 bcma_chipco_gpio_intmask(struct bcma_drv_cc *cc, u32 mask, u32 value) | 246 | u32 bcma_chipco_gpio_intmask(struct bcma_drv_cc *cc, u32 mask, u32 value) |
220 | { | 247 | { |
221 | return bcma_cc_write32_masked(cc, BCMA_CC_GPIOIRQ, mask, value); | 248 | unsigned long flags; |
249 | u32 res; | ||
250 | |||
251 | spin_lock_irqsave(&cc->gpio_lock, flags); | ||
252 | res = bcma_cc_write32_masked(cc, BCMA_CC_GPIOIRQ, mask, value); | ||
253 | spin_unlock_irqrestore(&cc->gpio_lock, flags); | ||
254 | |||
255 | return res; | ||
222 | } | 256 | } |
223 | 257 | ||
224 | u32 bcma_chipco_gpio_polarity(struct bcma_drv_cc *cc, u32 mask, u32 value) | 258 | u32 bcma_chipco_gpio_polarity(struct bcma_drv_cc *cc, u32 mask, u32 value) |
225 | { | 259 | { |
226 | return bcma_cc_write32_masked(cc, BCMA_CC_GPIOPOL, mask, value); | 260 | unsigned long flags; |
261 | u32 res; | ||
262 | |||
263 | spin_lock_irqsave(&cc->gpio_lock, flags); | ||
264 | res = bcma_cc_write32_masked(cc, BCMA_CC_GPIOPOL, mask, value); | ||
265 | spin_unlock_irqrestore(&cc->gpio_lock, flags); | ||
266 | |||
267 | return res; | ||
268 | } | ||
269 | |||
270 | u32 bcma_chipco_gpio_pullup(struct bcma_drv_cc *cc, u32 mask, u32 value) | ||
271 | { | ||
272 | unsigned long flags; | ||
273 | u32 res; | ||
274 | |||
275 | if (cc->core->id.rev < 20) | ||
276 | return 0; | ||
277 | |||
278 | spin_lock_irqsave(&cc->gpio_lock, flags); | ||
279 | res = bcma_cc_write32_masked(cc, BCMA_CC_GPIOPULLUP, mask, value); | ||
280 | spin_unlock_irqrestore(&cc->gpio_lock, flags); | ||
281 | |||
282 | return res; | ||
283 | } | ||
284 | |||
285 | u32 bcma_chipco_gpio_pulldown(struct bcma_drv_cc *cc, u32 mask, u32 value) | ||
286 | { | ||
287 | unsigned long flags; | ||
288 | u32 res; | ||
289 | |||
290 | if (cc->core->id.rev < 20) | ||
291 | return 0; | ||
292 | |||
293 | spin_lock_irqsave(&cc->gpio_lock, flags); | ||
294 | res = bcma_cc_write32_masked(cc, BCMA_CC_GPIOPULLDOWN, mask, value); | ||
295 | spin_unlock_irqrestore(&cc->gpio_lock, flags); | ||
296 | |||
297 | return res; | ||
227 | } | 298 | } |
228 | 299 | ||
229 | #ifdef CONFIG_BCMA_DRIVER_MIPS | 300 | #ifdef CONFIG_BCMA_DRIVER_MIPS |
diff --git a/drivers/bcma/driver_gpio.c b/drivers/bcma/driver_gpio.c new file mode 100644 index 000000000000..9a6f585da2d9 --- /dev/null +++ b/drivers/bcma/driver_gpio.c | |||
@@ -0,0 +1,98 @@ | |||
1 | /* | ||
2 | * Broadcom specific AMBA | ||
3 | * GPIO driver | ||
4 | * | ||
5 | * Copyright 2011, Broadcom Corporation | ||
6 | * Copyright 2012, Hauke Mehrtens <hauke@hauke-m.de> | ||
7 | * | ||
8 | * Licensed under the GNU/GPL. See COPYING for details. | ||
9 | */ | ||
10 | |||
11 | #include <linux/gpio.h> | ||
12 | #include <linux/export.h> | ||
13 | #include <linux/bcma/bcma.h> | ||
14 | |||
15 | #include "bcma_private.h" | ||
16 | |||
17 | static inline struct bcma_drv_cc *bcma_gpio_get_cc(struct gpio_chip *chip) | ||
18 | { | ||
19 | return container_of(chip, struct bcma_drv_cc, gpio); | ||
20 | } | ||
21 | |||
22 | static int bcma_gpio_get_value(struct gpio_chip *chip, unsigned gpio) | ||
23 | { | ||
24 | struct bcma_drv_cc *cc = bcma_gpio_get_cc(chip); | ||
25 | |||
26 | return !!bcma_chipco_gpio_in(cc, 1 << gpio); | ||
27 | } | ||
28 | |||
29 | static void bcma_gpio_set_value(struct gpio_chip *chip, unsigned gpio, | ||
30 | int value) | ||
31 | { | ||
32 | struct bcma_drv_cc *cc = bcma_gpio_get_cc(chip); | ||
33 | |||
34 | bcma_chipco_gpio_out(cc, 1 << gpio, value ? 1 << gpio : 0); | ||
35 | } | ||
36 | |||
37 | static int bcma_gpio_direction_input(struct gpio_chip *chip, unsigned gpio) | ||
38 | { | ||
39 | struct bcma_drv_cc *cc = bcma_gpio_get_cc(chip); | ||
40 | |||
41 | bcma_chipco_gpio_outen(cc, 1 << gpio, 0); | ||
42 | return 0; | ||
43 | } | ||
44 | |||
45 | static int bcma_gpio_direction_output(struct gpio_chip *chip, unsigned gpio, | ||
46 | int value) | ||
47 | { | ||
48 | struct bcma_drv_cc *cc = bcma_gpio_get_cc(chip); | ||
49 | |||
50 | bcma_chipco_gpio_outen(cc, 1 << gpio, 1 << gpio); | ||
51 | bcma_chipco_gpio_out(cc, 1 << gpio, value ? 1 << gpio : 0); | ||
52 | return 0; | ||
53 | } | ||
54 | |||
55 | static int bcma_gpio_request(struct gpio_chip *chip, unsigned gpio) | ||
56 | { | ||
57 | struct bcma_drv_cc *cc = bcma_gpio_get_cc(chip); | ||
58 | |||
59 | bcma_chipco_gpio_control(cc, 1 << gpio, 0); | ||
60 | /* clear pulldown */ | ||
61 | bcma_chipco_gpio_pulldown(cc, 1 << gpio, 0); | ||
62 | /* Set pullup */ | ||
63 | bcma_chipco_gpio_pullup(cc, 1 << gpio, 1 << gpio); | ||
64 | |||
65 | return 0; | ||
66 | } | ||
67 | |||
68 | static void bcma_gpio_free(struct gpio_chip *chip, unsigned gpio) | ||
69 | { | ||
70 | struct bcma_drv_cc *cc = bcma_gpio_get_cc(chip); | ||
71 | |||
72 | /* clear pullup */ | ||
73 | bcma_chipco_gpio_pullup(cc, 1 << gpio, 0); | ||
74 | } | ||
75 | |||
76 | int bcma_gpio_init(struct bcma_drv_cc *cc) | ||
77 | { | ||
78 | struct gpio_chip *chip = &cc->gpio; | ||
79 | |||
80 | chip->label = "bcma_gpio"; | ||
81 | chip->owner = THIS_MODULE; | ||
82 | chip->request = bcma_gpio_request; | ||
83 | chip->free = bcma_gpio_free; | ||
84 | chip->get = bcma_gpio_get_value; | ||
85 | chip->set = bcma_gpio_set_value; | ||
86 | chip->direction_input = bcma_gpio_direction_input; | ||
87 | chip->direction_output = bcma_gpio_direction_output; | ||
88 | chip->ngpio = 16; | ||
89 | /* There is just one SoC in one device and its GPIO addresses should be | ||
90 | * deterministic to address them more easily. The other buses could get | ||
91 | * a random base number. */ | ||
92 | if (cc->core->bus->hosttype == BCMA_HOSTTYPE_SOC) | ||
93 | chip->base = 0; | ||
94 | else | ||
95 | chip->base = -1; | ||
96 | |||
97 | return gpiochip_add(chip); | ||
98 | } | ||
diff --git a/drivers/bcma/main.c b/drivers/bcma/main.c index debd4f142f93..53ba20ca17e0 100644 --- a/drivers/bcma/main.c +++ b/drivers/bcma/main.c | |||
@@ -164,6 +164,11 @@ static int bcma_register_cores(struct bcma_bus *bus) | |||
164 | bcma_err(bus, "Error registering NAND flash\n"); | 164 | bcma_err(bus, "Error registering NAND flash\n"); |
165 | } | 165 | } |
166 | #endif | 166 | #endif |
167 | err = bcma_gpio_init(&bus->drv_cc); | ||
168 | if (err == -ENOTSUPP) | ||
169 | bcma_debug(bus, "GPIO driver not activated\n"); | ||
170 | else if (err) | ||
171 | bcma_err(bus, "Error registering GPIO driver: %i\n", err); | ||
167 | 172 | ||
168 | if (bus->hosttype == BCMA_HOSTTYPE_SOC) { | 173 | if (bus->hosttype == BCMA_HOSTTYPE_SOC) { |
169 | err = bcma_chipco_watchdog_register(&bus->drv_cc); | 174 | err = bcma_chipco_watchdog_register(&bus->drv_cc); |
diff --git a/drivers/edac/Kconfig b/drivers/edac/Kconfig index bb82d6be793c..4c6c876d9dc3 100644 --- a/drivers/edac/Kconfig +++ b/drivers/edac/Kconfig | |||
@@ -7,7 +7,7 @@ | |||
7 | menuconfig EDAC | 7 | menuconfig EDAC |
8 | bool "EDAC (Error Detection And Correction) reporting" | 8 | bool "EDAC (Error Detection And Correction) reporting" |
9 | depends on HAS_IOMEM | 9 | depends on HAS_IOMEM |
10 | depends on X86 || PPC || TILE || ARM | 10 | depends on X86 || PPC || TILE || ARM || EDAC_SUPPORT |
11 | help | 11 | help |
12 | EDAC is designed to report errors in the core system. | 12 | EDAC is designed to report errors in the core system. |
13 | These are low-level errors that are reported in the CPU or | 13 | These are low-level errors that are reported in the CPU or |
@@ -27,6 +27,9 @@ menuconfig EDAC | |||
27 | There is also a mailing list for the EDAC project, which can | 27 | There is also a mailing list for the EDAC project, which can |
28 | be found via the sourceforge page. | 28 | be found via the sourceforge page. |
29 | 29 | ||
30 | config EDAC_SUPPORT | ||
31 | bool | ||
32 | |||
30 | if EDAC | 33 | if EDAC |
31 | 34 | ||
32 | comment "Reporting subsystems" | 35 | comment "Reporting subsystems" |
@@ -316,4 +319,32 @@ config EDAC_HIGHBANK_L2 | |||
316 | Support for error detection and correction on the | 319 | Support for error detection and correction on the |
317 | Calxeda Highbank memory controller. | 320 | Calxeda Highbank memory controller. |
318 | 321 | ||
322 | config EDAC_OCTEON_PC | ||
323 | tristate "Cavium Octeon Primary Caches" | ||
324 | depends on EDAC_MM_EDAC && CPU_CAVIUM_OCTEON | ||
325 | help | ||
326 | Support for error detection and correction on the primary caches of | ||
327 | the cnMIPS cores of Cavium Octeon family SOCs. | ||
328 | |||
329 | config EDAC_OCTEON_L2C | ||
330 | tristate "Cavium Octeon Secondary Caches (L2C)" | ||
331 | depends on EDAC_MM_EDAC && CPU_CAVIUM_OCTEON | ||
332 | help | ||
333 | Support for error detection and correction on the | ||
334 | Cavium Octeon family of SOCs. | ||
335 | |||
336 | config EDAC_OCTEON_LMC | ||
337 | tristate "Cavium Octeon DRAM Memory Controller (LMC)" | ||
338 | depends on EDAC_MM_EDAC && CPU_CAVIUM_OCTEON | ||
339 | help | ||
340 | Support for error detection and correction on the | ||
341 | Cavium Octeon family of SOCs. | ||
342 | |||
343 | config EDAC_OCTEON_PCI | ||
344 | tristate "Cavium Octeon PCI Controller" | ||
345 | depends on EDAC_MM_EDAC && PCI && CPU_CAVIUM_OCTEON | ||
346 | help | ||
347 | Support for error detection and correction on the | ||
348 | Cavium Octeon family of SOCs. | ||
349 | |||
319 | endif # EDAC | 350 | endif # EDAC |
diff --git a/drivers/edac/Makefile b/drivers/edac/Makefile index 7e5129a733f8..5608a9ba61b7 100644 --- a/drivers/edac/Makefile +++ b/drivers/edac/Makefile | |||
@@ -58,3 +58,8 @@ obj-$(CONFIG_EDAC_TILE) += tile_edac.o | |||
58 | 58 | ||
59 | obj-$(CONFIG_EDAC_HIGHBANK_MC) += highbank_mc_edac.o | 59 | obj-$(CONFIG_EDAC_HIGHBANK_MC) += highbank_mc_edac.o |
60 | obj-$(CONFIG_EDAC_HIGHBANK_L2) += highbank_l2_edac.o | 60 | obj-$(CONFIG_EDAC_HIGHBANK_L2) += highbank_l2_edac.o |
61 | |||
62 | obj-$(CONFIG_EDAC_OCTEON_PC) += octeon_edac-pc.o | ||
63 | obj-$(CONFIG_EDAC_OCTEON_L2C) += octeon_edac-l2c.o | ||
64 | obj-$(CONFIG_EDAC_OCTEON_LMC) += octeon_edac-lmc.o | ||
65 | obj-$(CONFIG_EDAC_OCTEON_PCI) += octeon_edac-pci.o | ||
diff --git a/drivers/edac/octeon_edac-l2c.c b/drivers/edac/octeon_edac-l2c.c new file mode 100644 index 000000000000..40fde6a51ed6 --- /dev/null +++ b/drivers/edac/octeon_edac-l2c.c | |||
@@ -0,0 +1,208 @@ | |||
1 | /* | ||
2 | * This file is subject to the terms and conditions of the GNU General Public | ||
3 | * License. See the file "COPYING" in the main directory of this archive | ||
4 | * for more details. | ||
5 | * | ||
6 | * Copyright (C) 2012 Cavium, Inc. | ||
7 | * | ||
8 | * Copyright (C) 2009 Wind River Systems, | ||
9 | * written by Ralf Baechle <ralf@linux-mips.org> | ||
10 | */ | ||
11 | #include <linux/module.h> | ||
12 | #include <linux/init.h> | ||
13 | #include <linux/slab.h> | ||
14 | #include <linux/io.h> | ||
15 | #include <linux/edac.h> | ||
16 | |||
17 | #include <asm/octeon/cvmx.h> | ||
18 | |||
19 | #include "edac_core.h" | ||
20 | #include "edac_module.h" | ||
21 | |||
22 | #define EDAC_MOD_STR "octeon-l2c" | ||
23 | |||
24 | static void octeon_l2c_poll_oct1(struct edac_device_ctl_info *l2c) | ||
25 | { | ||
26 | union cvmx_l2t_err l2t_err, l2t_err_reset; | ||
27 | union cvmx_l2d_err l2d_err, l2d_err_reset; | ||
28 | |||
29 | l2t_err_reset.u64 = 0; | ||
30 | l2t_err.u64 = cvmx_read_csr(CVMX_L2T_ERR); | ||
31 | if (l2t_err.s.sec_err) { | ||
32 | edac_device_handle_ce(l2c, 0, 0, | ||
33 | "Tag Single bit error (corrected)"); | ||
34 | l2t_err_reset.s.sec_err = 1; | ||
35 | } | ||
36 | if (l2t_err.s.ded_err) { | ||
37 | edac_device_handle_ue(l2c, 0, 0, | ||
38 | "Tag Double bit error (detected)"); | ||
39 | l2t_err_reset.s.ded_err = 1; | ||
40 | } | ||
41 | if (l2t_err_reset.u64) | ||
42 | cvmx_write_csr(CVMX_L2T_ERR, l2t_err_reset.u64); | ||
43 | |||
44 | l2d_err_reset.u64 = 0; | ||
45 | l2d_err.u64 = cvmx_read_csr(CVMX_L2D_ERR); | ||
46 | if (l2d_err.s.sec_err) { | ||
47 | edac_device_handle_ce(l2c, 0, 1, | ||
48 | "Data Single bit error (corrected)"); | ||
49 | l2d_err_reset.s.sec_err = 1; | ||
50 | } | ||
51 | if (l2d_err.s.ded_err) { | ||
52 | edac_device_handle_ue(l2c, 0, 1, | ||
53 | "Data Double bit error (detected)"); | ||
54 | l2d_err_reset.s.ded_err = 1; | ||
55 | } | ||
56 | if (l2d_err_reset.u64) | ||
57 | cvmx_write_csr(CVMX_L2D_ERR, l2d_err_reset.u64); | ||
58 | |||
59 | } | ||
60 | |||
61 | static void _octeon_l2c_poll_oct2(struct edac_device_ctl_info *l2c, int tad) | ||
62 | { | ||
63 | union cvmx_l2c_err_tdtx err_tdtx, err_tdtx_reset; | ||
64 | union cvmx_l2c_err_ttgx err_ttgx, err_ttgx_reset; | ||
65 | char buf1[64]; | ||
66 | char buf2[80]; | ||
67 | |||
68 | err_tdtx_reset.u64 = 0; | ||
69 | err_tdtx.u64 = cvmx_read_csr(CVMX_L2C_ERR_TDTX(tad)); | ||
70 | if (err_tdtx.s.dbe || err_tdtx.s.sbe || | ||
71 | err_tdtx.s.vdbe || err_tdtx.s.vsbe) | ||
72 | snprintf(buf1, sizeof(buf1), | ||
73 | "type:%d, syn:0x%x, way:%d", | ||
74 | err_tdtx.s.type, err_tdtx.s.syn, err_tdtx.s.wayidx); | ||
75 | |||
76 | if (err_tdtx.s.dbe) { | ||
77 | snprintf(buf2, sizeof(buf2), | ||
78 | "L2D Double bit error (detected):%s", buf1); | ||
79 | err_tdtx_reset.s.dbe = 1; | ||
80 | edac_device_handle_ue(l2c, tad, 1, buf2); | ||
81 | } | ||
82 | if (err_tdtx.s.sbe) { | ||
83 | snprintf(buf2, sizeof(buf2), | ||
84 | "L2D Single bit error (corrected):%s", buf1); | ||
85 | err_tdtx_reset.s.sbe = 1; | ||
86 | edac_device_handle_ce(l2c, tad, 1, buf2); | ||
87 | } | ||
88 | if (err_tdtx.s.vdbe) { | ||
89 | snprintf(buf2, sizeof(buf2), | ||
90 | "VBF Double bit error (detected):%s", buf1); | ||
91 | err_tdtx_reset.s.vdbe = 1; | ||
92 | edac_device_handle_ue(l2c, tad, 1, buf2); | ||
93 | } | ||
94 | if (err_tdtx.s.vsbe) { | ||
95 | snprintf(buf2, sizeof(buf2), | ||
96 | "VBF Single bit error (corrected):%s", buf1); | ||
97 | err_tdtx_reset.s.vsbe = 1; | ||
98 | edac_device_handle_ce(l2c, tad, 1, buf2); | ||
99 | } | ||
100 | if (err_tdtx_reset.u64) | ||
101 | cvmx_write_csr(CVMX_L2C_ERR_TDTX(tad), err_tdtx_reset.u64); | ||
102 | |||
103 | err_ttgx_reset.u64 = 0; | ||
104 | err_ttgx.u64 = cvmx_read_csr(CVMX_L2C_ERR_TTGX(tad)); | ||
105 | |||
106 | if (err_ttgx.s.dbe || err_ttgx.s.sbe) | ||
107 | snprintf(buf1, sizeof(buf1), | ||
108 | "type:%d, syn:0x%x, way:%d", | ||
109 | err_ttgx.s.type, err_ttgx.s.syn, err_ttgx.s.wayidx); | ||
110 | |||
111 | if (err_ttgx.s.dbe) { | ||
112 | snprintf(buf2, sizeof(buf2), | ||
113 | "Tag Double bit error (detected):%s", buf1); | ||
114 | err_ttgx_reset.s.dbe = 1; | ||
115 | edac_device_handle_ue(l2c, tad, 0, buf2); | ||
116 | } | ||
117 | if (err_ttgx.s.sbe) { | ||
118 | snprintf(buf2, sizeof(buf2), | ||
119 | "Tag Single bit error (corrected):%s", buf1); | ||
120 | err_ttgx_reset.s.sbe = 1; | ||
121 | edac_device_handle_ce(l2c, tad, 0, buf2); | ||
122 | } | ||
123 | if (err_ttgx_reset.u64) | ||
124 | cvmx_write_csr(CVMX_L2C_ERR_TTGX(tad), err_ttgx_reset.u64); | ||
125 | } | ||
126 | |||
127 | static void octeon_l2c_poll_oct2(struct edac_device_ctl_info *l2c) | ||
128 | { | ||
129 | int i; | ||
130 | for (i = 0; i < l2c->nr_instances; i++) | ||
131 | _octeon_l2c_poll_oct2(l2c, i); | ||
132 | } | ||
133 | |||
134 | static int __devinit octeon_l2c_probe(struct platform_device *pdev) | ||
135 | { | ||
136 | struct edac_device_ctl_info *l2c; | ||
137 | |||
138 | int num_tads = OCTEON_IS_MODEL(OCTEON_CN68XX) ? 4 : 1; | ||
139 | |||
140 | /* 'Tags' are block 0, 'Data' is block 1*/ | ||
141 | l2c = edac_device_alloc_ctl_info(0, "l2c", num_tads, "l2c", 2, 0, | ||
142 | NULL, 0, edac_device_alloc_index()); | ||
143 | if (!l2c) | ||
144 | return -ENOMEM; | ||
145 | |||
146 | l2c->dev = &pdev->dev; | ||
147 | platform_set_drvdata(pdev, l2c); | ||
148 | l2c->dev_name = dev_name(&pdev->dev); | ||
149 | |||
150 | l2c->mod_name = "octeon-l2c"; | ||
151 | l2c->ctl_name = "octeon_l2c_err"; | ||
152 | |||
153 | |||
154 | if (OCTEON_IS_MODEL(OCTEON_FAM_1_PLUS)) { | ||
155 | union cvmx_l2t_err l2t_err; | ||
156 | union cvmx_l2d_err l2d_err; | ||
157 | |||
158 | l2t_err.u64 = cvmx_read_csr(CVMX_L2T_ERR); | ||
159 | l2t_err.s.sec_intena = 0; /* We poll */ | ||
160 | l2t_err.s.ded_intena = 0; | ||
161 | cvmx_write_csr(CVMX_L2T_ERR, l2t_err.u64); | ||
162 | |||
163 | l2d_err.u64 = cvmx_read_csr(CVMX_L2D_ERR); | ||
164 | l2d_err.s.sec_intena = 0; /* We poll */ | ||
165 | l2d_err.s.ded_intena = 0; | ||
166 | cvmx_write_csr(CVMX_L2T_ERR, l2d_err.u64); | ||
167 | |||
168 | l2c->edac_check = octeon_l2c_poll_oct1; | ||
169 | } else { | ||
170 | /* OCTEON II */ | ||
171 | l2c->edac_check = octeon_l2c_poll_oct2; | ||
172 | } | ||
173 | |||
174 | if (edac_device_add_device(l2c) > 0) { | ||
175 | pr_err("%s: edac_device_add_device() failed\n", __func__); | ||
176 | goto err; | ||
177 | } | ||
178 | |||
179 | |||
180 | return 0; | ||
181 | |||
182 | err: | ||
183 | edac_device_free_ctl_info(l2c); | ||
184 | |||
185 | return -ENXIO; | ||
186 | } | ||
187 | |||
188 | static int octeon_l2c_remove(struct platform_device *pdev) | ||
189 | { | ||
190 | struct edac_device_ctl_info *l2c = platform_get_drvdata(pdev); | ||
191 | |||
192 | edac_device_del_device(&pdev->dev); | ||
193 | edac_device_free_ctl_info(l2c); | ||
194 | |||
195 | return 0; | ||
196 | } | ||
197 | |||
198 | static struct platform_driver octeon_l2c_driver = { | ||
199 | .probe = octeon_l2c_probe, | ||
200 | .remove = octeon_l2c_remove, | ||
201 | .driver = { | ||
202 | .name = "octeon_l2c_edac", | ||
203 | } | ||
204 | }; | ||
205 | module_platform_driver(octeon_l2c_driver); | ||
206 | |||
207 | MODULE_LICENSE("GPL"); | ||
208 | MODULE_AUTHOR("Ralf Baechle <ralf@linux-mips.org>"); | ||
diff --git a/drivers/edac/octeon_edac-lmc.c b/drivers/edac/octeon_edac-lmc.c new file mode 100644 index 000000000000..33bca766e37d --- /dev/null +++ b/drivers/edac/octeon_edac-lmc.c | |||
@@ -0,0 +1,186 @@ | |||
1 | /* | ||
2 | * This file is subject to the terms and conditions of the GNU General Public | ||
3 | * License. See the file "COPYING" in the main directory of this archive | ||
4 | * for more details. | ||
5 | * | ||
6 | * Copyright (C) 2009 Wind River Systems, | ||
7 | * written by Ralf Baechle <ralf@linux-mips.org> | ||
8 | */ | ||
9 | #include <linux/module.h> | ||
10 | #include <linux/init.h> | ||
11 | #include <linux/slab.h> | ||
12 | #include <linux/io.h> | ||
13 | #include <linux/edac.h> | ||
14 | |||
15 | #include <asm/octeon/octeon.h> | ||
16 | #include <asm/octeon/cvmx-lmcx-defs.h> | ||
17 | |||
18 | #include "edac_core.h" | ||
19 | #include "edac_module.h" | ||
20 | |||
21 | #define OCTEON_MAX_MC 4 | ||
22 | |||
23 | static void octeon_lmc_edac_poll(struct mem_ctl_info *mci) | ||
24 | { | ||
25 | union cvmx_lmcx_mem_cfg0 cfg0; | ||
26 | bool do_clear = false; | ||
27 | char msg[64]; | ||
28 | |||
29 | cfg0.u64 = cvmx_read_csr(CVMX_LMCX_MEM_CFG0(mci->mc_idx)); | ||
30 | if (cfg0.s.sec_err || cfg0.s.ded_err) { | ||
31 | union cvmx_lmcx_fadr fadr; | ||
32 | fadr.u64 = cvmx_read_csr(CVMX_LMCX_FADR(mci->mc_idx)); | ||
33 | snprintf(msg, sizeof(msg), | ||
34 | "DIMM %d rank %d bank %d row %d col %d", | ||
35 | fadr.cn30xx.fdimm, fadr.cn30xx.fbunk, | ||
36 | fadr.cn30xx.fbank, fadr.cn30xx.frow, fadr.cn30xx.fcol); | ||
37 | } | ||
38 | |||
39 | if (cfg0.s.sec_err) { | ||
40 | edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, 1, 0, 0, 0, | ||
41 | -1, -1, -1, msg, ""); | ||
42 | cfg0.s.sec_err = -1; /* Done, re-arm */ | ||
43 | do_clear = true; | ||
44 | } | ||
45 | |||
46 | if (cfg0.s.ded_err) { | ||
47 | edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 1, 0, 0, 0, | ||
48 | -1, -1, -1, msg, ""); | ||
49 | cfg0.s.ded_err = -1; /* Done, re-arm */ | ||
50 | do_clear = true; | ||
51 | } | ||
52 | if (do_clear) | ||
53 | cvmx_write_csr(CVMX_LMCX_MEM_CFG0(mci->mc_idx), cfg0.u64); | ||
54 | } | ||
55 | |||
56 | static void octeon_lmc_edac_poll_o2(struct mem_ctl_info *mci) | ||
57 | { | ||
58 | union cvmx_lmcx_int int_reg; | ||
59 | bool do_clear = false; | ||
60 | char msg[64]; | ||
61 | |||
62 | int_reg.u64 = cvmx_read_csr(CVMX_LMCX_INT(mci->mc_idx)); | ||
63 | if (int_reg.s.sec_err || int_reg.s.ded_err) { | ||
64 | union cvmx_lmcx_fadr fadr; | ||
65 | fadr.u64 = cvmx_read_csr(CVMX_LMCX_FADR(mci->mc_idx)); | ||
66 | snprintf(msg, sizeof(msg), | ||
67 | "DIMM %d rank %d bank %d row %d col %d", | ||
68 | fadr.cn61xx.fdimm, fadr.cn61xx.fbunk, | ||
69 | fadr.cn61xx.fbank, fadr.cn61xx.frow, fadr.cn61xx.fcol); | ||
70 | } | ||
71 | |||
72 | if (int_reg.s.sec_err) { | ||
73 | edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, 1, 0, 0, 0, | ||
74 | -1, -1, -1, msg, ""); | ||
75 | int_reg.s.sec_err = -1; /* Done, re-arm */ | ||
76 | do_clear = true; | ||
77 | } | ||
78 | |||
79 | if (int_reg.s.ded_err) { | ||
80 | edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 1, 0, 0, 0, | ||
81 | -1, -1, -1, msg, ""); | ||
82 | int_reg.s.ded_err = -1; /* Done, re-arm */ | ||
83 | do_clear = true; | ||
84 | } | ||
85 | if (do_clear) | ||
86 | cvmx_write_csr(CVMX_LMCX_INT(mci->mc_idx), int_reg.u64); | ||
87 | } | ||
88 | |||
89 | static int __devinit octeon_lmc_edac_probe(struct platform_device *pdev) | ||
90 | { | ||
91 | struct mem_ctl_info *mci; | ||
92 | struct edac_mc_layer layers[1]; | ||
93 | int mc = pdev->id; | ||
94 | |||
95 | layers[0].type = EDAC_MC_LAYER_CHANNEL; | ||
96 | layers[0].size = 1; | ||
97 | layers[0].is_virt_csrow = false; | ||
98 | |||
99 | if (OCTEON_IS_MODEL(OCTEON_FAM_1_PLUS)) { | ||
100 | union cvmx_lmcx_mem_cfg0 cfg0; | ||
101 | |||
102 | cfg0.u64 = cvmx_read_csr(CVMX_LMCX_MEM_CFG0(0)); | ||
103 | if (!cfg0.s.ecc_ena) { | ||
104 | dev_info(&pdev->dev, "Disabled (ECC not enabled)\n"); | ||
105 | return 0; | ||
106 | } | ||
107 | |||
108 | mci = edac_mc_alloc(mc, ARRAY_SIZE(layers), layers, 0); | ||
109 | if (!mci) | ||
110 | return -ENXIO; | ||
111 | |||
112 | mci->pdev = &pdev->dev; | ||
113 | mci->dev_name = dev_name(&pdev->dev); | ||
114 | |||
115 | mci->mod_name = "octeon-lmc"; | ||
116 | mci->ctl_name = "octeon-lmc-err"; | ||
117 | mci->edac_check = octeon_lmc_edac_poll; | ||
118 | |||
119 | if (edac_mc_add_mc(mci)) { | ||
120 | dev_err(&pdev->dev, "edac_mc_add_mc() failed\n"); | ||
121 | edac_mc_free(mci); | ||
122 | return -ENXIO; | ||
123 | } | ||
124 | |||
125 | cfg0.u64 = cvmx_read_csr(CVMX_LMCX_MEM_CFG0(mc)); | ||
126 | cfg0.s.intr_ded_ena = 0; /* We poll */ | ||
127 | cfg0.s.intr_sec_ena = 0; | ||
128 | cvmx_write_csr(CVMX_LMCX_MEM_CFG0(mc), cfg0.u64); | ||
129 | } else { | ||
130 | /* OCTEON II */ | ||
131 | union cvmx_lmcx_int_en en; | ||
132 | union cvmx_lmcx_config config; | ||
133 | |||
134 | config.u64 = cvmx_read_csr(CVMX_LMCX_CONFIG(0)); | ||
135 | if (!config.s.ecc_ena) { | ||
136 | dev_info(&pdev->dev, "Disabled (ECC not enabled)\n"); | ||
137 | return 0; | ||
138 | } | ||
139 | |||
140 | mci = edac_mc_alloc(mc, ARRAY_SIZE(layers), layers, 0); | ||
141 | if (!mci) | ||
142 | return -ENXIO; | ||
143 | |||
144 | mci->pdev = &pdev->dev; | ||
145 | mci->dev_name = dev_name(&pdev->dev); | ||
146 | |||
147 | mci->mod_name = "octeon-lmc"; | ||
148 | mci->ctl_name = "co_lmc_err"; | ||
149 | mci->edac_check = octeon_lmc_edac_poll_o2; | ||
150 | |||
151 | if (edac_mc_add_mc(mci)) { | ||
152 | dev_err(&pdev->dev, "edac_mc_add_mc() failed\n"); | ||
153 | edac_mc_free(mci); | ||
154 | return -ENXIO; | ||
155 | } | ||
156 | |||
157 | en.u64 = cvmx_read_csr(CVMX_LMCX_MEM_CFG0(mc)); | ||
158 | en.s.intr_ded_ena = 0; /* We poll */ | ||
159 | en.s.intr_sec_ena = 0; | ||
160 | cvmx_write_csr(CVMX_LMCX_MEM_CFG0(mc), en.u64); | ||
161 | } | ||
162 | platform_set_drvdata(pdev, mci); | ||
163 | |||
164 | return 0; | ||
165 | } | ||
166 | |||
167 | static int octeon_lmc_edac_remove(struct platform_device *pdev) | ||
168 | { | ||
169 | struct mem_ctl_info *mci = platform_get_drvdata(pdev); | ||
170 | |||
171 | edac_mc_del_mc(&pdev->dev); | ||
172 | edac_mc_free(mci); | ||
173 | return 0; | ||
174 | } | ||
175 | |||
176 | static struct platform_driver octeon_lmc_edac_driver = { | ||
177 | .probe = octeon_lmc_edac_probe, | ||
178 | .remove = octeon_lmc_edac_remove, | ||
179 | .driver = { | ||
180 | .name = "octeon_lmc_edac", | ||
181 | } | ||
182 | }; | ||
183 | module_platform_driver(octeon_lmc_edac_driver); | ||
184 | |||
185 | MODULE_LICENSE("GPL"); | ||
186 | MODULE_AUTHOR("Ralf Baechle <ralf@linux-mips.org>"); | ||
diff --git a/drivers/edac/octeon_edac-pc.c b/drivers/edac/octeon_edac-pc.c new file mode 100644 index 000000000000..14a5e57f2b32 --- /dev/null +++ b/drivers/edac/octeon_edac-pc.c | |||
@@ -0,0 +1,143 @@ | |||
1 | /* | ||
2 | * This file is subject to the terms and conditions of the GNU General Public | ||
3 | * License. See the file "COPYING" in the main directory of this archive | ||
4 | * for more details. | ||
5 | * | ||
6 | * Copyright (C) 2012 Cavium, Inc. | ||
7 | * | ||
8 | * Copyright (C) 2009 Wind River Systems, | ||
9 | * written by Ralf Baechle <ralf@linux-mips.org> | ||
10 | */ | ||
11 | #include <linux/module.h> | ||
12 | #include <linux/init.h> | ||
13 | #include <linux/slab.h> | ||
14 | #include <linux/interrupt.h> | ||
15 | #include <linux/io.h> | ||
16 | #include <linux/edac.h> | ||
17 | |||
18 | #include "edac_core.h" | ||
19 | #include "edac_module.h" | ||
20 | |||
21 | #include <asm/octeon/cvmx.h> | ||
22 | #include <asm/mipsregs.h> | ||
23 | |||
24 | extern int register_co_cache_error_notifier(struct notifier_block *nb); | ||
25 | extern int unregister_co_cache_error_notifier(struct notifier_block *nb); | ||
26 | |||
27 | extern unsigned long long cache_err_dcache[NR_CPUS]; | ||
28 | |||
29 | struct co_cache_error { | ||
30 | struct notifier_block notifier; | ||
31 | struct edac_device_ctl_info *ed; | ||
32 | }; | ||
33 | |||
34 | /** | ||
35 | * EDAC CPU cache error callback | ||
36 | * | ||
37 | * @event: non-zero if unrecoverable. | ||
38 | */ | ||
39 | static int co_cache_error_event(struct notifier_block *this, | ||
40 | unsigned long event, void *ptr) | ||
41 | { | ||
42 | struct co_cache_error *p = container_of(this, struct co_cache_error, | ||
43 | notifier); | ||
44 | |||
45 | unsigned int core = cvmx_get_core_num(); | ||
46 | unsigned int cpu = smp_processor_id(); | ||
47 | u64 icache_err = read_octeon_c0_icacheerr(); | ||
48 | u64 dcache_err; | ||
49 | |||
50 | if (event) { | ||
51 | dcache_err = cache_err_dcache[core]; | ||
52 | cache_err_dcache[core] = 0; | ||
53 | } else { | ||
54 | dcache_err = read_octeon_c0_dcacheerr(); | ||
55 | } | ||
56 | |||
57 | if (icache_err & 1) { | ||
58 | edac_device_printk(p->ed, KERN_ERR, | ||
59 | "CacheErr (Icache):%llx, core %d/cpu %d, cp0_errorepc == %lx\n", | ||
60 | (unsigned long long)icache_err, core, cpu, | ||
61 | read_c0_errorepc()); | ||
62 | write_octeon_c0_icacheerr(0); | ||
63 | edac_device_handle_ce(p->ed, cpu, 1, "icache"); | ||
64 | } | ||
65 | if (dcache_err & 1) { | ||
66 | edac_device_printk(p->ed, KERN_ERR, | ||
67 | "CacheErr (Dcache):%llx, core %d/cpu %d, cp0_errorepc == %lx\n", | ||
68 | (unsigned long long)dcache_err, core, cpu, | ||
69 | read_c0_errorepc()); | ||
70 | if (event) | ||
71 | edac_device_handle_ue(p->ed, cpu, 0, "dcache"); | ||
72 | else | ||
73 | edac_device_handle_ce(p->ed, cpu, 0, "dcache"); | ||
74 | |||
75 | /* Clear the error indication */ | ||
76 | if (OCTEON_IS_MODEL(OCTEON_FAM_2)) | ||
77 | write_octeon_c0_dcacheerr(1); | ||
78 | else | ||
79 | write_octeon_c0_dcacheerr(0); | ||
80 | } | ||
81 | |||
82 | return NOTIFY_STOP; | ||
83 | } | ||
84 | |||
85 | static int __devinit co_cache_error_probe(struct platform_device *pdev) | ||
86 | { | ||
87 | struct co_cache_error *p = devm_kzalloc(&pdev->dev, sizeof(*p), | ||
88 | GFP_KERNEL); | ||
89 | if (!p) | ||
90 | return -ENOMEM; | ||
91 | |||
92 | p->notifier.notifier_call = co_cache_error_event; | ||
93 | platform_set_drvdata(pdev, p); | ||
94 | |||
95 | p->ed = edac_device_alloc_ctl_info(0, "cpu", num_possible_cpus(), | ||
96 | "cache", 2, 0, NULL, 0, | ||
97 | edac_device_alloc_index()); | ||
98 | if (!p->ed) | ||
99 | goto err; | ||
100 | |||
101 | p->ed->dev = &pdev->dev; | ||
102 | |||
103 | p->ed->dev_name = dev_name(&pdev->dev); | ||
104 | |||
105 | p->ed->mod_name = "octeon-cpu"; | ||
106 | p->ed->ctl_name = "cache"; | ||
107 | |||
108 | if (edac_device_add_device(p->ed)) { | ||
109 | pr_err("%s: edac_device_add_device() failed\n", __func__); | ||
110 | goto err1; | ||
111 | } | ||
112 | |||
113 | register_co_cache_error_notifier(&p->notifier); | ||
114 | |||
115 | return 0; | ||
116 | |||
117 | err1: | ||
118 | edac_device_free_ctl_info(p->ed); | ||
119 | err: | ||
120 | return -ENXIO; | ||
121 | } | ||
122 | |||
123 | static int co_cache_error_remove(struct platform_device *pdev) | ||
124 | { | ||
125 | struct co_cache_error *p = platform_get_drvdata(pdev); | ||
126 | |||
127 | unregister_co_cache_error_notifier(&p->notifier); | ||
128 | edac_device_del_device(&pdev->dev); | ||
129 | edac_device_free_ctl_info(p->ed); | ||
130 | return 0; | ||
131 | } | ||
132 | |||
133 | static struct platform_driver co_cache_error_driver = { | ||
134 | .probe = co_cache_error_probe, | ||
135 | .remove = co_cache_error_remove, | ||
136 | .driver = { | ||
137 | .name = "octeon_pc_edac", | ||
138 | } | ||
139 | }; | ||
140 | module_platform_driver(co_cache_error_driver); | ||
141 | |||
142 | MODULE_LICENSE("GPL"); | ||
143 | MODULE_AUTHOR("Ralf Baechle <ralf@linux-mips.org>"); | ||
diff --git a/drivers/edac/octeon_edac-pci.c b/drivers/edac/octeon_edac-pci.c new file mode 100644 index 000000000000..758c1ef5fc9e --- /dev/null +++ b/drivers/edac/octeon_edac-pci.c | |||
@@ -0,0 +1,111 @@ | |||
1 | /* | ||
2 | * This file is subject to the terms and conditions of the GNU General Public | ||
3 | * License. See the file "COPYING" in the main directory of this archive | ||
4 | * for more details. | ||
5 | * | ||
6 | * Copyright (C) 2012 Cavium, Inc. | ||
7 | * Copyright (C) 2009 Wind River Systems, | ||
8 | * written by Ralf Baechle <ralf@linux-mips.org> | ||
9 | */ | ||
10 | #include <linux/module.h> | ||
11 | #include <linux/init.h> | ||
12 | #include <linux/slab.h> | ||
13 | #include <linux/io.h> | ||
14 | #include <linux/edac.h> | ||
15 | |||
16 | #include <asm/octeon/cvmx.h> | ||
17 | #include <asm/octeon/cvmx-npi-defs.h> | ||
18 | #include <asm/octeon/cvmx-pci-defs.h> | ||
19 | #include <asm/octeon/octeon.h> | ||
20 | |||
21 | #include "edac_core.h" | ||
22 | #include "edac_module.h" | ||
23 | |||
24 | static void octeon_pci_poll(struct edac_pci_ctl_info *pci) | ||
25 | { | ||
26 | union cvmx_pci_cfg01 cfg01; | ||
27 | |||
28 | cfg01.u32 = octeon_npi_read32(CVMX_NPI_PCI_CFG01); | ||
29 | if (cfg01.s.dpe) { /* Detected parity error */ | ||
30 | edac_pci_handle_pe(pci, pci->ctl_name); | ||
31 | cfg01.s.dpe = 1; /* Reset */ | ||
32 | octeon_npi_write32(CVMX_NPI_PCI_CFG01, cfg01.u32); | ||
33 | } | ||
34 | if (cfg01.s.sse) { | ||
35 | edac_pci_handle_npe(pci, "Signaled System Error"); | ||
36 | cfg01.s.sse = 1; /* Reset */ | ||
37 | octeon_npi_write32(CVMX_NPI_PCI_CFG01, cfg01.u32); | ||
38 | } | ||
39 | if (cfg01.s.rma) { | ||
40 | edac_pci_handle_npe(pci, "Received Master Abort"); | ||
41 | cfg01.s.rma = 1; /* Reset */ | ||
42 | octeon_npi_write32(CVMX_NPI_PCI_CFG01, cfg01.u32); | ||
43 | } | ||
44 | if (cfg01.s.rta) { | ||
45 | edac_pci_handle_npe(pci, "Received Target Abort"); | ||
46 | cfg01.s.rta = 1; /* Reset */ | ||
47 | octeon_npi_write32(CVMX_NPI_PCI_CFG01, cfg01.u32); | ||
48 | } | ||
49 | if (cfg01.s.sta) { | ||
50 | edac_pci_handle_npe(pci, "Signaled Target Abort"); | ||
51 | cfg01.s.sta = 1; /* Reset */ | ||
52 | octeon_npi_write32(CVMX_NPI_PCI_CFG01, cfg01.u32); | ||
53 | } | ||
54 | if (cfg01.s.mdpe) { | ||
55 | edac_pci_handle_npe(pci, "Master Data Parity Error"); | ||
56 | cfg01.s.mdpe = 1; /* Reset */ | ||
57 | octeon_npi_write32(CVMX_NPI_PCI_CFG01, cfg01.u32); | ||
58 | } | ||
59 | } | ||
60 | |||
61 | static int __devinit octeon_pci_probe(struct platform_device *pdev) | ||
62 | { | ||
63 | struct edac_pci_ctl_info *pci; | ||
64 | int res = 0; | ||
65 | |||
66 | pci = edac_pci_alloc_ctl_info(0, "octeon_pci_err"); | ||
67 | if (!pci) | ||
68 | return -ENOMEM; | ||
69 | |||
70 | pci->dev = &pdev->dev; | ||
71 | platform_set_drvdata(pdev, pci); | ||
72 | pci->dev_name = dev_name(&pdev->dev); | ||
73 | |||
74 | pci->mod_name = "octeon-pci"; | ||
75 | pci->ctl_name = "octeon_pci_err"; | ||
76 | pci->edac_check = octeon_pci_poll; | ||
77 | |||
78 | if (edac_pci_add_device(pci, 0) > 0) { | ||
79 | pr_err("%s: edac_pci_add_device() failed\n", __func__); | ||
80 | goto err; | ||
81 | } | ||
82 | |||
83 | return 0; | ||
84 | |||
85 | err: | ||
86 | edac_pci_free_ctl_info(pci); | ||
87 | |||
88 | return res; | ||
89 | } | ||
90 | |||
91 | static int octeon_pci_remove(struct platform_device *pdev) | ||
92 | { | ||
93 | struct edac_pci_ctl_info *pci = platform_get_drvdata(pdev); | ||
94 | |||
95 | edac_pci_del_device(&pdev->dev); | ||
96 | edac_pci_free_ctl_info(pci); | ||
97 | |||
98 | return 0; | ||
99 | } | ||
100 | |||
101 | static struct platform_driver octeon_pci_driver = { | ||
102 | .probe = octeon_pci_probe, | ||
103 | .remove = octeon_pci_remove, | ||
104 | .driver = { | ||
105 | .name = "octeon_pci_edac", | ||
106 | } | ||
107 | }; | ||
108 | module_platform_driver(octeon_pci_driver); | ||
109 | |||
110 | MODULE_LICENSE("GPL"); | ||
111 | MODULE_AUTHOR("Ralf Baechle <ralf@linux-mips.org>"); | ||
diff --git a/drivers/ssb/Kconfig b/drivers/ssb/Kconfig index 42cdaa9a4d8a..ff3c8a21f10d 100644 --- a/drivers/ssb/Kconfig +++ b/drivers/ssb/Kconfig | |||
@@ -160,4 +160,13 @@ config SSB_DRIVER_GIGE | |||
160 | 160 | ||
161 | If unsure, say N | 161 | If unsure, say N |
162 | 162 | ||
163 | config SSB_DRIVER_GPIO | ||
164 | bool "SSB GPIO driver" | ||
165 | depends on SSB | ||
166 | select GPIOLIB | ||
167 | help | ||
168 | Driver to provide access to the GPIO pins on the bus. | ||
169 | |||
170 | If unsure, say N | ||
171 | |||
163 | endmenu | 172 | endmenu |
diff --git a/drivers/ssb/Makefile b/drivers/ssb/Makefile index 656e58b92618..9159ba77c388 100644 --- a/drivers/ssb/Makefile +++ b/drivers/ssb/Makefile | |||
@@ -15,6 +15,7 @@ ssb-$(CONFIG_SSB_DRIVER_MIPS) += driver_mipscore.o | |||
15 | ssb-$(CONFIG_SSB_DRIVER_EXTIF) += driver_extif.o | 15 | ssb-$(CONFIG_SSB_DRIVER_EXTIF) += driver_extif.o |
16 | ssb-$(CONFIG_SSB_DRIVER_PCICORE) += driver_pcicore.o | 16 | ssb-$(CONFIG_SSB_DRIVER_PCICORE) += driver_pcicore.o |
17 | ssb-$(CONFIG_SSB_DRIVER_GIGE) += driver_gige.o | 17 | ssb-$(CONFIG_SSB_DRIVER_GIGE) += driver_gige.o |
18 | ssb-$(CONFIG_SSB_DRIVER_GPIO) += driver_gpio.o | ||
18 | 19 | ||
19 | # b43 pci-ssb-bridge driver | 20 | # b43 pci-ssb-bridge driver |
20 | # Not strictly a part of SSB, but kept here for convenience | 21 | # Not strictly a part of SSB, but kept here for convenience |
diff --git a/drivers/ssb/driver_chipcommon.c b/drivers/ssb/driver_chipcommon.c index 95c33a05f434..71098a7b5fed 100644 --- a/drivers/ssb/driver_chipcommon.c +++ b/drivers/ssb/driver_chipcommon.c | |||
@@ -349,6 +349,9 @@ void ssb_chipcommon_init(struct ssb_chipcommon *cc) | |||
349 | { | 349 | { |
350 | if (!cc->dev) | 350 | if (!cc->dev) |
351 | return; /* We don't have a ChipCommon */ | 351 | return; /* We don't have a ChipCommon */ |
352 | |||
353 | spin_lock_init(&cc->gpio_lock); | ||
354 | |||
352 | if (cc->dev->id.revision >= 11) | 355 | if (cc->dev->id.revision >= 11) |
353 | cc->status = chipco_read32(cc, SSB_CHIPCO_CHIPSTAT); | 356 | cc->status = chipco_read32(cc, SSB_CHIPCO_CHIPSTAT); |
354 | ssb_dprintk(KERN_INFO PFX "chipcommon status is 0x%x\n", cc->status); | 357 | ssb_dprintk(KERN_INFO PFX "chipcommon status is 0x%x\n", cc->status); |
@@ -505,28 +508,93 @@ u32 ssb_chipco_gpio_in(struct ssb_chipcommon *cc, u32 mask) | |||
505 | 508 | ||
506 | u32 ssb_chipco_gpio_out(struct ssb_chipcommon *cc, u32 mask, u32 value) | 509 | u32 ssb_chipco_gpio_out(struct ssb_chipcommon *cc, u32 mask, u32 value) |
507 | { | 510 | { |
508 | return chipco_write32_masked(cc, SSB_CHIPCO_GPIOOUT, mask, value); | 511 | unsigned long flags; |
512 | u32 res = 0; | ||
513 | |||
514 | spin_lock_irqsave(&cc->gpio_lock, flags); | ||
515 | res = chipco_write32_masked(cc, SSB_CHIPCO_GPIOOUT, mask, value); | ||
516 | spin_unlock_irqrestore(&cc->gpio_lock, flags); | ||
517 | |||
518 | return res; | ||
509 | } | 519 | } |
510 | 520 | ||
511 | u32 ssb_chipco_gpio_outen(struct ssb_chipcommon *cc, u32 mask, u32 value) | 521 | u32 ssb_chipco_gpio_outen(struct ssb_chipcommon *cc, u32 mask, u32 value) |
512 | { | 522 | { |
513 | return chipco_write32_masked(cc, SSB_CHIPCO_GPIOOUTEN, mask, value); | 523 | unsigned long flags; |
524 | u32 res = 0; | ||
525 | |||
526 | spin_lock_irqsave(&cc->gpio_lock, flags); | ||
527 | res = chipco_write32_masked(cc, SSB_CHIPCO_GPIOOUTEN, mask, value); | ||
528 | spin_unlock_irqrestore(&cc->gpio_lock, flags); | ||
529 | |||
530 | return res; | ||
514 | } | 531 | } |
515 | 532 | ||
516 | u32 ssb_chipco_gpio_control(struct ssb_chipcommon *cc, u32 mask, u32 value) | 533 | u32 ssb_chipco_gpio_control(struct ssb_chipcommon *cc, u32 mask, u32 value) |
517 | { | 534 | { |
518 | return chipco_write32_masked(cc, SSB_CHIPCO_GPIOCTL, mask, value); | 535 | unsigned long flags; |
536 | u32 res = 0; | ||
537 | |||
538 | spin_lock_irqsave(&cc->gpio_lock, flags); | ||
539 | res = chipco_write32_masked(cc, SSB_CHIPCO_GPIOCTL, mask, value); | ||
540 | spin_unlock_irqrestore(&cc->gpio_lock, flags); | ||
541 | |||
542 | return res; | ||
519 | } | 543 | } |
520 | EXPORT_SYMBOL(ssb_chipco_gpio_control); | 544 | EXPORT_SYMBOL(ssb_chipco_gpio_control); |
521 | 545 | ||
522 | u32 ssb_chipco_gpio_intmask(struct ssb_chipcommon *cc, u32 mask, u32 value) | 546 | u32 ssb_chipco_gpio_intmask(struct ssb_chipcommon *cc, u32 mask, u32 value) |
523 | { | 547 | { |
524 | return chipco_write32_masked(cc, SSB_CHIPCO_GPIOIRQ, mask, value); | 548 | unsigned long flags; |
549 | u32 res = 0; | ||
550 | |||
551 | spin_lock_irqsave(&cc->gpio_lock, flags); | ||
552 | res = chipco_write32_masked(cc, SSB_CHIPCO_GPIOIRQ, mask, value); | ||
553 | spin_unlock_irqrestore(&cc->gpio_lock, flags); | ||
554 | |||
555 | return res; | ||
525 | } | 556 | } |
526 | 557 | ||
527 | u32 ssb_chipco_gpio_polarity(struct ssb_chipcommon *cc, u32 mask, u32 value) | 558 | u32 ssb_chipco_gpio_polarity(struct ssb_chipcommon *cc, u32 mask, u32 value) |
528 | { | 559 | { |
529 | return chipco_write32_masked(cc, SSB_CHIPCO_GPIOPOL, mask, value); | 560 | unsigned long flags; |
561 | u32 res = 0; | ||
562 | |||
563 | spin_lock_irqsave(&cc->gpio_lock, flags); | ||
564 | res = chipco_write32_masked(cc, SSB_CHIPCO_GPIOPOL, mask, value); | ||
565 | spin_unlock_irqrestore(&cc->gpio_lock, flags); | ||
566 | |||
567 | return res; | ||
568 | } | ||
569 | |||
570 | u32 ssb_chipco_gpio_pullup(struct ssb_chipcommon *cc, u32 mask, u32 value) | ||
571 | { | ||
572 | unsigned long flags; | ||
573 | u32 res = 0; | ||
574 | |||
575 | if (cc->dev->id.revision < 20) | ||
576 | return 0xffffffff; | ||
577 | |||
578 | spin_lock_irqsave(&cc->gpio_lock, flags); | ||
579 | res = chipco_write32_masked(cc, SSB_CHIPCO_GPIOPULLUP, mask, value); | ||
580 | spin_unlock_irqrestore(&cc->gpio_lock, flags); | ||
581 | |||
582 | return res; | ||
583 | } | ||
584 | |||
585 | u32 ssb_chipco_gpio_pulldown(struct ssb_chipcommon *cc, u32 mask, u32 value) | ||
586 | { | ||
587 | unsigned long flags; | ||
588 | u32 res = 0; | ||
589 | |||
590 | if (cc->dev->id.revision < 20) | ||
591 | return 0xffffffff; | ||
592 | |||
593 | spin_lock_irqsave(&cc->gpio_lock, flags); | ||
594 | res = chipco_write32_masked(cc, SSB_CHIPCO_GPIOPULLDOWN, mask, value); | ||
595 | spin_unlock_irqrestore(&cc->gpio_lock, flags); | ||
596 | |||
597 | return res; | ||
530 | } | 598 | } |
531 | 599 | ||
532 | #ifdef CONFIG_SSB_SERIAL | 600 | #ifdef CONFIG_SSB_SERIAL |
diff --git a/drivers/ssb/driver_extif.c b/drivers/ssb/driver_extif.c index 553227a3062d..59385fdab5b0 100644 --- a/drivers/ssb/driver_extif.c +++ b/drivers/ssb/driver_extif.c | |||
@@ -138,6 +138,13 @@ u32 ssb_extif_watchdog_timer_set(struct ssb_extif *extif, u32 ticks) | |||
138 | return ticks; | 138 | return ticks; |
139 | } | 139 | } |
140 | 140 | ||
141 | void ssb_extif_init(struct ssb_extif *extif) | ||
142 | { | ||
143 | if (!extif->dev) | ||
144 | return; /* We don't have a Extif core */ | ||
145 | spin_lock_init(&extif->gpio_lock); | ||
146 | } | ||
147 | |||
141 | u32 ssb_extif_gpio_in(struct ssb_extif *extif, u32 mask) | 148 | u32 ssb_extif_gpio_in(struct ssb_extif *extif, u32 mask) |
142 | { | 149 | { |
143 | return extif_read32(extif, SSB_EXTIF_GPIO_IN) & mask; | 150 | return extif_read32(extif, SSB_EXTIF_GPIO_IN) & mask; |
@@ -145,22 +152,50 @@ u32 ssb_extif_gpio_in(struct ssb_extif *extif, u32 mask) | |||
145 | 152 | ||
146 | u32 ssb_extif_gpio_out(struct ssb_extif *extif, u32 mask, u32 value) | 153 | u32 ssb_extif_gpio_out(struct ssb_extif *extif, u32 mask, u32 value) |
147 | { | 154 | { |
148 | return extif_write32_masked(extif, SSB_EXTIF_GPIO_OUT(0), | 155 | unsigned long flags; |
156 | u32 res = 0; | ||
157 | |||
158 | spin_lock_irqsave(&extif->gpio_lock, flags); | ||
159 | res = extif_write32_masked(extif, SSB_EXTIF_GPIO_OUT(0), | ||
149 | mask, value); | 160 | mask, value); |
161 | spin_unlock_irqrestore(&extif->gpio_lock, flags); | ||
162 | |||
163 | return res; | ||
150 | } | 164 | } |
151 | 165 | ||
152 | u32 ssb_extif_gpio_outen(struct ssb_extif *extif, u32 mask, u32 value) | 166 | u32 ssb_extif_gpio_outen(struct ssb_extif *extif, u32 mask, u32 value) |
153 | { | 167 | { |
154 | return extif_write32_masked(extif, SSB_EXTIF_GPIO_OUTEN(0), | 168 | unsigned long flags; |
169 | u32 res = 0; | ||
170 | |||
171 | spin_lock_irqsave(&extif->gpio_lock, flags); | ||
172 | res = extif_write32_masked(extif, SSB_EXTIF_GPIO_OUTEN(0), | ||
155 | mask, value); | 173 | mask, value); |
174 | spin_unlock_irqrestore(&extif->gpio_lock, flags); | ||
175 | |||
176 | return res; | ||
156 | } | 177 | } |
157 | 178 | ||
158 | u32 ssb_extif_gpio_polarity(struct ssb_extif *extif, u32 mask, u32 value) | 179 | u32 ssb_extif_gpio_polarity(struct ssb_extif *extif, u32 mask, u32 value) |
159 | { | 180 | { |
160 | return extif_write32_masked(extif, SSB_EXTIF_GPIO_INTPOL, mask, value); | 181 | unsigned long flags; |
182 | u32 res = 0; | ||
183 | |||
184 | spin_lock_irqsave(&extif->gpio_lock, flags); | ||
185 | res = extif_write32_masked(extif, SSB_EXTIF_GPIO_INTPOL, mask, value); | ||
186 | spin_unlock_irqrestore(&extif->gpio_lock, flags); | ||
187 | |||
188 | return res; | ||
161 | } | 189 | } |
162 | 190 | ||
163 | u32 ssb_extif_gpio_intmask(struct ssb_extif *extif, u32 mask, u32 value) | 191 | u32 ssb_extif_gpio_intmask(struct ssb_extif *extif, u32 mask, u32 value) |
164 | { | 192 | { |
165 | return extif_write32_masked(extif, SSB_EXTIF_GPIO_INTMASK, mask, value); | 193 | unsigned long flags; |
194 | u32 res = 0; | ||
195 | |||
196 | spin_lock_irqsave(&extif->gpio_lock, flags); | ||
197 | res = extif_write32_masked(extif, SSB_EXTIF_GPIO_INTMASK, mask, value); | ||
198 | spin_unlock_irqrestore(&extif->gpio_lock, flags); | ||
199 | |||
200 | return res; | ||
166 | } | 201 | } |
diff --git a/drivers/ssb/driver_gpio.c b/drivers/ssb/driver_gpio.c new file mode 100644 index 000000000000..97ac0a38e3d0 --- /dev/null +++ b/drivers/ssb/driver_gpio.c | |||
@@ -0,0 +1,176 @@ | |||
1 | /* | ||
2 | * Sonics Silicon Backplane | ||
3 | * GPIO driver | ||
4 | * | ||
5 | * Copyright 2011, Broadcom Corporation | ||
6 | * Copyright 2012, Hauke Mehrtens <hauke@hauke-m.de> | ||
7 | * | ||
8 | * Licensed under the GNU/GPL. See COPYING for details. | ||
9 | */ | ||
10 | |||
11 | #include <linux/gpio.h> | ||
12 | #include <linux/export.h> | ||
13 | #include <linux/ssb/ssb.h> | ||
14 | |||
15 | #include "ssb_private.h" | ||
16 | |||
17 | static struct ssb_bus *ssb_gpio_get_bus(struct gpio_chip *chip) | ||
18 | { | ||
19 | return container_of(chip, struct ssb_bus, gpio); | ||
20 | } | ||
21 | |||
22 | static int ssb_gpio_chipco_get_value(struct gpio_chip *chip, unsigned gpio) | ||
23 | { | ||
24 | struct ssb_bus *bus = ssb_gpio_get_bus(chip); | ||
25 | |||
26 | return !!ssb_chipco_gpio_in(&bus->chipco, 1 << gpio); | ||
27 | } | ||
28 | |||
29 | static void ssb_gpio_chipco_set_value(struct gpio_chip *chip, unsigned gpio, | ||
30 | int value) | ||
31 | { | ||
32 | struct ssb_bus *bus = ssb_gpio_get_bus(chip); | ||
33 | |||
34 | ssb_chipco_gpio_out(&bus->chipco, 1 << gpio, value ? 1 << gpio : 0); | ||
35 | } | ||
36 | |||
37 | static int ssb_gpio_chipco_direction_input(struct gpio_chip *chip, | ||
38 | unsigned gpio) | ||
39 | { | ||
40 | struct ssb_bus *bus = ssb_gpio_get_bus(chip); | ||
41 | |||
42 | ssb_chipco_gpio_outen(&bus->chipco, 1 << gpio, 0); | ||
43 | return 0; | ||
44 | } | ||
45 | |||
46 | static int ssb_gpio_chipco_direction_output(struct gpio_chip *chip, | ||
47 | unsigned gpio, int value) | ||
48 | { | ||
49 | struct ssb_bus *bus = ssb_gpio_get_bus(chip); | ||
50 | |||
51 | ssb_chipco_gpio_outen(&bus->chipco, 1 << gpio, 1 << gpio); | ||
52 | ssb_chipco_gpio_out(&bus->chipco, 1 << gpio, value ? 1 << gpio : 0); | ||
53 | return 0; | ||
54 | } | ||
55 | |||
56 | static int ssb_gpio_chipco_request(struct gpio_chip *chip, unsigned gpio) | ||
57 | { | ||
58 | struct ssb_bus *bus = ssb_gpio_get_bus(chip); | ||
59 | |||
60 | ssb_chipco_gpio_control(&bus->chipco, 1 << gpio, 0); | ||
61 | /* clear pulldown */ | ||
62 | ssb_chipco_gpio_pulldown(&bus->chipco, 1 << gpio, 0); | ||
63 | /* Set pullup */ | ||
64 | ssb_chipco_gpio_pullup(&bus->chipco, 1 << gpio, 1 << gpio); | ||
65 | |||
66 | return 0; | ||
67 | } | ||
68 | |||
69 | static void ssb_gpio_chipco_free(struct gpio_chip *chip, unsigned gpio) | ||
70 | { | ||
71 | struct ssb_bus *bus = ssb_gpio_get_bus(chip); | ||
72 | |||
73 | /* clear pullup */ | ||
74 | ssb_chipco_gpio_pullup(&bus->chipco, 1 << gpio, 0); | ||
75 | } | ||
76 | |||
77 | static int ssb_gpio_chipco_init(struct ssb_bus *bus) | ||
78 | { | ||
79 | struct gpio_chip *chip = &bus->gpio; | ||
80 | |||
81 | chip->label = "ssb_chipco_gpio"; | ||
82 | chip->owner = THIS_MODULE; | ||
83 | chip->request = ssb_gpio_chipco_request; | ||
84 | chip->free = ssb_gpio_chipco_free; | ||
85 | chip->get = ssb_gpio_chipco_get_value; | ||
86 | chip->set = ssb_gpio_chipco_set_value; | ||
87 | chip->direction_input = ssb_gpio_chipco_direction_input; | ||
88 | chip->direction_output = ssb_gpio_chipco_direction_output; | ||
89 | chip->ngpio = 16; | ||
90 | /* There is just one SoC in one device and its GPIO addresses should be | ||
91 | * deterministic to address them more easily. The other buses could get | ||
92 | * a random base number. */ | ||
93 | if (bus->bustype == SSB_BUSTYPE_SSB) | ||
94 | chip->base = 0; | ||
95 | else | ||
96 | chip->base = -1; | ||
97 | |||
98 | return gpiochip_add(chip); | ||
99 | } | ||
100 | |||
101 | #ifdef CONFIG_SSB_DRIVER_EXTIF | ||
102 | |||
103 | static int ssb_gpio_extif_get_value(struct gpio_chip *chip, unsigned gpio) | ||
104 | { | ||
105 | struct ssb_bus *bus = ssb_gpio_get_bus(chip); | ||
106 | |||
107 | return !!ssb_extif_gpio_in(&bus->extif, 1 << gpio); | ||
108 | } | ||
109 | |||
110 | static void ssb_gpio_extif_set_value(struct gpio_chip *chip, unsigned gpio, | ||
111 | int value) | ||
112 | { | ||
113 | struct ssb_bus *bus = ssb_gpio_get_bus(chip); | ||
114 | |||
115 | ssb_extif_gpio_out(&bus->extif, 1 << gpio, value ? 1 << gpio : 0); | ||
116 | } | ||
117 | |||
118 | static int ssb_gpio_extif_direction_input(struct gpio_chip *chip, | ||
119 | unsigned gpio) | ||
120 | { | ||
121 | struct ssb_bus *bus = ssb_gpio_get_bus(chip); | ||
122 | |||
123 | ssb_extif_gpio_outen(&bus->extif, 1 << gpio, 0); | ||
124 | return 0; | ||
125 | } | ||
126 | |||
127 | static int ssb_gpio_extif_direction_output(struct gpio_chip *chip, | ||
128 | unsigned gpio, int value) | ||
129 | { | ||
130 | struct ssb_bus *bus = ssb_gpio_get_bus(chip); | ||
131 | |||
132 | ssb_extif_gpio_outen(&bus->extif, 1 << gpio, 1 << gpio); | ||
133 | ssb_extif_gpio_out(&bus->extif, 1 << gpio, value ? 1 << gpio : 0); | ||
134 | return 0; | ||
135 | } | ||
136 | |||
137 | static int ssb_gpio_extif_init(struct ssb_bus *bus) | ||
138 | { | ||
139 | struct gpio_chip *chip = &bus->gpio; | ||
140 | |||
141 | chip->label = "ssb_extif_gpio"; | ||
142 | chip->owner = THIS_MODULE; | ||
143 | chip->get = ssb_gpio_extif_get_value; | ||
144 | chip->set = ssb_gpio_extif_set_value; | ||
145 | chip->direction_input = ssb_gpio_extif_direction_input; | ||
146 | chip->direction_output = ssb_gpio_extif_direction_output; | ||
147 | chip->ngpio = 5; | ||
148 | /* There is just one SoC in one device and its GPIO addresses should be | ||
149 | * deterministic to address them more easily. The other buses could get | ||
150 | * a random base number. */ | ||
151 | if (bus->bustype == SSB_BUSTYPE_SSB) | ||
152 | chip->base = 0; | ||
153 | else | ||
154 | chip->base = -1; | ||
155 | |||
156 | return gpiochip_add(chip); | ||
157 | } | ||
158 | |||
159 | #else | ||
160 | static int ssb_gpio_extif_init(struct ssb_bus *bus) | ||
161 | { | ||
162 | return -ENOTSUPP; | ||
163 | } | ||
164 | #endif | ||
165 | |||
166 | int ssb_gpio_init(struct ssb_bus *bus) | ||
167 | { | ||
168 | if (ssb_chipco_available(&bus->chipco)) | ||
169 | return ssb_gpio_chipco_init(bus); | ||
170 | else if (ssb_extif_available(&bus->extif)) | ||
171 | return ssb_gpio_extif_init(bus); | ||
172 | else | ||
173 | SSB_WARN_ON(1); | ||
174 | |||
175 | return -1; | ||
176 | } | ||
diff --git a/drivers/ssb/main.c b/drivers/ssb/main.c index 6e0daaa0e04b..c82c5c95fe85 100644 --- a/drivers/ssb/main.c +++ b/drivers/ssb/main.c | |||
@@ -804,7 +804,14 @@ static int __devinit ssb_bus_register(struct ssb_bus *bus, | |||
804 | if (err) | 804 | if (err) |
805 | goto err_pcmcia_exit; | 805 | goto err_pcmcia_exit; |
806 | ssb_chipcommon_init(&bus->chipco); | 806 | ssb_chipcommon_init(&bus->chipco); |
807 | ssb_extif_init(&bus->extif); | ||
807 | ssb_mipscore_init(&bus->mipscore); | 808 | ssb_mipscore_init(&bus->mipscore); |
809 | err = ssb_gpio_init(bus); | ||
810 | if (err == -ENOTSUPP) | ||
811 | ssb_dprintk(KERN_DEBUG PFX "GPIO driver not activated\n"); | ||
812 | else if (err) | ||
813 | ssb_dprintk(KERN_ERR PFX | ||
814 | "Error registering GPIO driver: %i\n", err); | ||
808 | err = ssb_fetch_invariants(bus, get_invariants); | 815 | err = ssb_fetch_invariants(bus, get_invariants); |
809 | if (err) { | 816 | if (err) { |
810 | ssb_bus_may_powerdown(bus); | 817 | ssb_bus_may_powerdown(bus); |
diff --git a/drivers/ssb/ssb_private.h b/drivers/ssb/ssb_private.h index 8942db1d855a..6c10b66c796c 100644 --- a/drivers/ssb/ssb_private.h +++ b/drivers/ssb/ssb_private.h | |||
@@ -242,4 +242,21 @@ static inline int ssb_watchdog_register(struct ssb_bus *bus) | |||
242 | } | 242 | } |
243 | #endif /* CONFIG_SSB_EMBEDDED */ | 243 | #endif /* CONFIG_SSB_EMBEDDED */ |
244 | 244 | ||
245 | #ifdef CONFIG_SSB_DRIVER_EXTIF | ||
246 | extern void ssb_extif_init(struct ssb_extif *extif); | ||
247 | #else | ||
248 | static inline void ssb_extif_init(struct ssb_extif *extif) | ||
249 | { | ||
250 | } | ||
251 | #endif | ||
252 | |||
253 | #ifdef CONFIG_SSB_DRIVER_GPIO | ||
254 | extern int ssb_gpio_init(struct ssb_bus *bus); | ||
255 | #else /* CONFIG_SSB_DRIVER_GPIO */ | ||
256 | static inline int ssb_gpio_init(struct ssb_bus *bus) | ||
257 | { | ||
258 | return -ENOTSUPP; | ||
259 | } | ||
260 | #endif /* CONFIG_SSB_DRIVER_GPIO */ | ||
261 | |||
245 | #endif /* LINUX_SSB_PRIVATE_H_ */ | 262 | #endif /* LINUX_SSB_PRIVATE_H_ */ |
diff --git a/drivers/video/console/newport_con.c b/drivers/video/console/newport_con.c index 6d1596629040..b05afd03729e 100644 --- a/drivers/video/console/newport_con.c +++ b/drivers/video/console/newport_con.c | |||
@@ -327,9 +327,16 @@ out_unmap: | |||
327 | 327 | ||
328 | static void newport_init(struct vc_data *vc, int init) | 328 | static void newport_init(struct vc_data *vc, int init) |
329 | { | 329 | { |
330 | vc->vc_cols = newport_xsize / 8; | 330 | int cols, rows; |
331 | vc->vc_rows = newport_ysize / 16; | 331 | |
332 | cols = newport_xsize / 8; | ||
333 | rows = newport_ysize / 16; | ||
332 | vc->vc_can_do_color = 1; | 334 | vc->vc_can_do_color = 1; |
335 | if (init) { | ||
336 | vc->vc_cols = cols; | ||
337 | vc->vc_rows = rows; | ||
338 | } else | ||
339 | vc_resize(vc, cols, rows); | ||
333 | } | 340 | } |
334 | 341 | ||
335 | static void newport_deinit(struct vc_data *c) | 342 | static void newport_deinit(struct vc_data *c) |