diff options
Diffstat (limited to 'arch/mips/cavium-octeon')
-rw-r--r-- | arch/mips/cavium-octeon/Makefile | 2 | ||||
-rw-r--r-- | arch/mips/cavium-octeon/cpu.c | 52 | ||||
-rw-r--r-- | arch/mips/cavium-octeon/csrc-octeon.c | 32 | ||||
-rw-r--r-- | arch/mips/cavium-octeon/dma-octeon.c | 10 | ||||
-rw-r--r-- | arch/mips/cavium-octeon/executive/cvmx-bootmem.c | 6 | ||||
-rw-r--r-- | arch/mips/cavium-octeon/executive/cvmx-sysinfo.c | 1 | ||||
-rw-r--r-- | arch/mips/cavium-octeon/octeon-irq.c | 160 | ||||
-rw-r--r-- | arch/mips/cavium-octeon/octeon-platform.c | 173 | ||||
-rw-r--r-- | arch/mips/cavium-octeon/setup.c | 82 | ||||
-rw-r--r-- | arch/mips/cavium-octeon/smp.c | 10 |
10 files changed, 385 insertions, 143 deletions
diff --git a/arch/mips/cavium-octeon/Makefile b/arch/mips/cavium-octeon/Makefile index 139436280520..3e9876317e61 100644 --- a/arch/mips/cavium-octeon/Makefile +++ b/arch/mips/cavium-octeon/Makefile | |||
@@ -9,7 +9,7 @@ | |||
9 | # Copyright (C) 2005-2009 Cavium Networks | 9 | # Copyright (C) 2005-2009 Cavium Networks |
10 | # | 10 | # |
11 | 11 | ||
12 | obj-y := setup.o serial.o octeon-platform.o octeon-irq.o csrc-octeon.o | 12 | obj-y := cpu.o setup.o serial.o octeon-platform.o octeon-irq.o csrc-octeon.o |
13 | obj-y += dma-octeon.o flash_setup.o | 13 | obj-y += dma-octeon.o flash_setup.o |
14 | obj-y += octeon-memcpy.o | 14 | obj-y += octeon-memcpy.o |
15 | 15 | ||
diff --git a/arch/mips/cavium-octeon/cpu.c b/arch/mips/cavium-octeon/cpu.c new file mode 100644 index 000000000000..b6df5387e855 --- /dev/null +++ b/arch/mips/cavium-octeon/cpu.c | |||
@@ -0,0 +1,52 @@ | |||
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/init.h> | ||
10 | #include <linux/irqflags.h> | ||
11 | #include <linux/notifier.h> | ||
12 | #include <linux/prefetch.h> | ||
13 | #include <linux/sched.h> | ||
14 | |||
15 | #include <asm/cop2.h> | ||
16 | #include <asm/current.h> | ||
17 | #include <asm/mipsregs.h> | ||
18 | #include <asm/page.h> | ||
19 | #include <asm/octeon/octeon.h> | ||
20 | |||
21 | static int cnmips_cu2_call(struct notifier_block *nfb, unsigned long action, | ||
22 | void *data) | ||
23 | { | ||
24 | unsigned long flags; | ||
25 | unsigned int status; | ||
26 | |||
27 | switch (action) { | ||
28 | case CU2_EXCEPTION: | ||
29 | prefetch(¤t->thread.cp2); | ||
30 | local_irq_save(flags); | ||
31 | KSTK_STATUS(current) |= ST0_CU2; | ||
32 | status = read_c0_status(); | ||
33 | write_c0_status(status | ST0_CU2); | ||
34 | octeon_cop2_restore(&(current->thread.cp2)); | ||
35 | write_c0_status(status & ~ST0_CU2); | ||
36 | local_irq_restore(flags); | ||
37 | |||
38 | return NOTIFY_BAD; /* Don't call default notifier */ | ||
39 | } | ||
40 | |||
41 | return NOTIFY_OK; /* Let default notifier send signals */ | ||
42 | } | ||
43 | |||
44 | static struct notifier_block cnmips_cu2_notifier = { | ||
45 | .notifier_call = cnmips_cu2_call, | ||
46 | }; | ||
47 | |||
48 | static int cnmips_cu2_setup(void) | ||
49 | { | ||
50 | return register_cu2_notifier(&cnmips_cu2_notifier); | ||
51 | } | ||
52 | early_initcall(cnmips_cu2_setup); | ||
diff --git a/arch/mips/cavium-octeon/csrc-octeon.c b/arch/mips/cavium-octeon/csrc-octeon.c index 96110f217dcd..0bf4bbe04ae2 100644 --- a/arch/mips/cavium-octeon/csrc-octeon.c +++ b/arch/mips/cavium-octeon/csrc-octeon.c | |||
@@ -50,6 +50,38 @@ static struct clocksource clocksource_mips = { | |||
50 | .flags = CLOCK_SOURCE_IS_CONTINUOUS, | 50 | .flags = CLOCK_SOURCE_IS_CONTINUOUS, |
51 | }; | 51 | }; |
52 | 52 | ||
53 | unsigned long long notrace sched_clock(void) | ||
54 | { | ||
55 | /* 64-bit arithmatic can overflow, so use 128-bit. */ | ||
56 | #if (__GNUC__ < 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ <= 3)) | ||
57 | u64 t1, t2, t3; | ||
58 | unsigned long long rv; | ||
59 | u64 mult = clocksource_mips.mult; | ||
60 | u64 shift = clocksource_mips.shift; | ||
61 | u64 cnt = read_c0_cvmcount(); | ||
62 | |||
63 | asm ( | ||
64 | "dmultu\t%[cnt],%[mult]\n\t" | ||
65 | "nor\t%[t1],$0,%[shift]\n\t" | ||
66 | "mfhi\t%[t2]\n\t" | ||
67 | "mflo\t%[t3]\n\t" | ||
68 | "dsll\t%[t2],%[t2],1\n\t" | ||
69 | "dsrlv\t%[rv],%[t3],%[shift]\n\t" | ||
70 | "dsllv\t%[t1],%[t2],%[t1]\n\t" | ||
71 | "or\t%[rv],%[t1],%[rv]\n\t" | ||
72 | : [rv] "=&r" (rv), [t1] "=&r" (t1), [t2] "=&r" (t2), [t3] "=&r" (t3) | ||
73 | : [cnt] "r" (cnt), [mult] "r" (mult), [shift] "r" (shift) | ||
74 | : "hi", "lo"); | ||
75 | return rv; | ||
76 | #else | ||
77 | /* GCC > 4.3 do it the easy way. */ | ||
78 | unsigned int __attribute__((mode(TI))) t; | ||
79 | t = read_c0_cvmcount(); | ||
80 | t = t * clocksource_mips.mult; | ||
81 | return (unsigned long long)(t >> clocksource_mips.shift); | ||
82 | #endif | ||
83 | } | ||
84 | |||
53 | void __init plat_time_init(void) | 85 | void __init plat_time_init(void) |
54 | { | 86 | { |
55 | clocksource_mips.rating = 300; | 87 | clocksource_mips.rating = 300; |
diff --git a/arch/mips/cavium-octeon/dma-octeon.c b/arch/mips/cavium-octeon/dma-octeon.c index 4b92bfc662db..be531ec1f206 100644 --- a/arch/mips/cavium-octeon/dma-octeon.c +++ b/arch/mips/cavium-octeon/dma-octeon.c | |||
@@ -41,7 +41,7 @@ struct bar1_index_state { | |||
41 | }; | 41 | }; |
42 | 42 | ||
43 | #ifdef CONFIG_PCI | 43 | #ifdef CONFIG_PCI |
44 | static DEFINE_SPINLOCK(bar1_lock); | 44 | static DEFINE_RAW_SPINLOCK(bar1_lock); |
45 | static struct bar1_index_state bar1_state[32]; | 45 | static struct bar1_index_state bar1_state[32]; |
46 | #endif | 46 | #endif |
47 | 47 | ||
@@ -198,7 +198,7 @@ dma_addr_t octeon_map_dma_mem(struct device *dev, void *ptr, size_t size) | |||
198 | start_index = 31; | 198 | start_index = 31; |
199 | 199 | ||
200 | /* Only one processor can access the Bar register at once */ | 200 | /* Only one processor can access the Bar register at once */ |
201 | spin_lock_irqsave(&bar1_lock, flags); | 201 | raw_spin_lock_irqsave(&bar1_lock, flags); |
202 | 202 | ||
203 | /* Look through Bar1 for existing mapping that will work */ | 203 | /* Look through Bar1 for existing mapping that will work */ |
204 | for (index = start_index; index >= 0; index--) { | 204 | for (index = start_index; index >= 0; index--) { |
@@ -250,7 +250,7 @@ dma_addr_t octeon_map_dma_mem(struct device *dev, void *ptr, size_t size) | |||
250 | (unsigned long long) physical); | 250 | (unsigned long long) physical); |
251 | 251 | ||
252 | done_unlock: | 252 | done_unlock: |
253 | spin_unlock_irqrestore(&bar1_lock, flags); | 253 | raw_spin_unlock_irqrestore(&bar1_lock, flags); |
254 | done: | 254 | done: |
255 | pr_debug("dma_map_single 0x%llx->0x%llx\n", physical, result); | 255 | pr_debug("dma_map_single 0x%llx->0x%llx\n", physical, result); |
256 | return result; | 256 | return result; |
@@ -324,14 +324,14 @@ void octeon_unmap_dma_mem(struct device *dev, dma_addr_t dma_addr) | |||
324 | "Attempt to unmap an invalid address (0x%llx)\n", | 324 | "Attempt to unmap an invalid address (0x%llx)\n", |
325 | dma_addr); | 325 | dma_addr); |
326 | 326 | ||
327 | spin_lock_irqsave(&bar1_lock, flags); | 327 | raw_spin_lock_irqsave(&bar1_lock, flags); |
328 | bar1_state[index].ref_count--; | 328 | bar1_state[index].ref_count--; |
329 | if (bar1_state[index].ref_count == 0) | 329 | if (bar1_state[index].ref_count == 0) |
330 | octeon_npi_write32(CVMX_NPI_PCI_BAR1_INDEXX(index), 0); | 330 | octeon_npi_write32(CVMX_NPI_PCI_BAR1_INDEXX(index), 0); |
331 | else if (unlikely(bar1_state[index].ref_count < 0)) | 331 | else if (unlikely(bar1_state[index].ref_count < 0)) |
332 | panic("dma_unmap_single: Bar1[%u] reference count < 0\n", | 332 | panic("dma_unmap_single: Bar1[%u] reference count < 0\n", |
333 | (int) index); | 333 | (int) index); |
334 | spin_unlock_irqrestore(&bar1_lock, flags); | 334 | raw_spin_unlock_irqrestore(&bar1_lock, flags); |
335 | done: | 335 | done: |
336 | pr_debug("dma_unmap_single 0x%llx\n", dma_addr); | 336 | pr_debug("dma_unmap_single 0x%llx\n", dma_addr); |
337 | return; | 337 | return; |
diff --git a/arch/mips/cavium-octeon/executive/cvmx-bootmem.c b/arch/mips/cavium-octeon/executive/cvmx-bootmem.c index 25666da17b22..fdf5f19bfdb0 100644 --- a/arch/mips/cavium-octeon/executive/cvmx-bootmem.c +++ b/arch/mips/cavium-octeon/executive/cvmx-bootmem.c | |||
@@ -253,7 +253,7 @@ int64_t cvmx_bootmem_phy_alloc(uint64_t req_size, uint64_t address_min, | |||
253 | * impossible requests up front. (NOP for address_min == 0) | 253 | * impossible requests up front. (NOP for address_min == 0) |
254 | */ | 254 | */ |
255 | if (alignment) | 255 | if (alignment) |
256 | address_min = __ALIGN_MASK(address_min, (alignment - 1)); | 256 | address_min = ALIGN(address_min, alignment); |
257 | 257 | ||
258 | /* | 258 | /* |
259 | * Reject inconsistent args. We have adjusted these, so this | 259 | * Reject inconsistent args. We have adjusted these, so this |
@@ -291,7 +291,7 @@ int64_t cvmx_bootmem_phy_alloc(uint64_t req_size, uint64_t address_min, | |||
291 | * satisfy request. | 291 | * satisfy request. |
292 | */ | 292 | */ |
293 | usable_base = | 293 | usable_base = |
294 | __ALIGN_MASK(max(address_min, ent_addr), alignment - 1); | 294 | ALIGN(max(address_min, ent_addr), alignment); |
295 | usable_max = min(address_max, ent_addr + ent_size); | 295 | usable_max = min(address_max, ent_addr + ent_size); |
296 | /* | 296 | /* |
297 | * We should be able to allocate block at address | 297 | * We should be able to allocate block at address |
@@ -671,7 +671,7 @@ int64_t cvmx_bootmem_phy_named_block_alloc(uint64_t size, uint64_t min_addr, | |||
671 | * coallesced when they are freed. The alloc routine does the | 671 | * coallesced when they are freed. The alloc routine does the |
672 | * same rounding up on all allocations. | 672 | * same rounding up on all allocations. |
673 | */ | 673 | */ |
674 | size = __ALIGN_MASK(size, (CVMX_BOOTMEM_ALIGNMENT_SIZE - 1)); | 674 | size = ALIGN(size, CVMX_BOOTMEM_ALIGNMENT_SIZE); |
675 | 675 | ||
676 | addr_allocated = cvmx_bootmem_phy_alloc(size, min_addr, max_addr, | 676 | addr_allocated = cvmx_bootmem_phy_alloc(size, min_addr, max_addr, |
677 | alignment, | 677 | alignment, |
diff --git a/arch/mips/cavium-octeon/executive/cvmx-sysinfo.c b/arch/mips/cavium-octeon/executive/cvmx-sysinfo.c index e5838890cba5..8b18a20cc7b3 100644 --- a/arch/mips/cavium-octeon/executive/cvmx-sysinfo.c +++ b/arch/mips/cavium-octeon/executive/cvmx-sysinfo.c | |||
@@ -115,4 +115,3 @@ int cvmx_sysinfo_minimal_initialize(void *phy_mem_desc_ptr, | |||
115 | 115 | ||
116 | return 1; | 116 | return 1; |
117 | } | 117 | } |
118 | |||
diff --git a/arch/mips/cavium-octeon/octeon-irq.c b/arch/mips/cavium-octeon/octeon-irq.c index 6f2acf09328d..c424cd158dc6 100644 --- a/arch/mips/cavium-octeon/octeon-irq.c +++ b/arch/mips/cavium-octeon/octeon-irq.c | |||
@@ -13,9 +13,8 @@ | |||
13 | #include <asm/octeon/cvmx-pexp-defs.h> | 13 | #include <asm/octeon/cvmx-pexp-defs.h> |
14 | #include <asm/octeon/cvmx-npi-defs.h> | 14 | #include <asm/octeon/cvmx-npi-defs.h> |
15 | 15 | ||
16 | DEFINE_RWLOCK(octeon_irq_ciu0_rwlock); | 16 | static DEFINE_RAW_SPINLOCK(octeon_irq_ciu0_lock); |
17 | DEFINE_RWLOCK(octeon_irq_ciu1_rwlock); | 17 | static DEFINE_RAW_SPINLOCK(octeon_irq_ciu1_lock); |
18 | DEFINE_SPINLOCK(octeon_irq_msi_lock); | ||
19 | 18 | ||
20 | static int octeon_coreid_for_cpu(int cpu) | 19 | static int octeon_coreid_for_cpu(int cpu) |
21 | { | 20 | { |
@@ -51,9 +50,6 @@ static void octeon_irq_core_eoi(unsigned int irq) | |||
51 | */ | 50 | */ |
52 | if (desc->status & IRQ_DISABLED) | 51 | if (desc->status & IRQ_DISABLED) |
53 | return; | 52 | return; |
54 | |||
55 | /* There is a race here. We should fix it. */ | ||
56 | |||
57 | /* | 53 | /* |
58 | * We don't need to disable IRQs to make these atomic since | 54 | * We don't need to disable IRQs to make these atomic since |
59 | * they are already disabled earlier in the low level | 55 | * they are already disabled earlier in the low level |
@@ -141,19 +137,12 @@ static void octeon_irq_ciu0_enable(unsigned int irq) | |||
141 | uint64_t en0; | 137 | uint64_t en0; |
142 | int bit = irq - OCTEON_IRQ_WORKQ0; /* Bit 0-63 of EN0 */ | 138 | int bit = irq - OCTEON_IRQ_WORKQ0; /* Bit 0-63 of EN0 */ |
143 | 139 | ||
144 | /* | 140 | raw_spin_lock_irqsave(&octeon_irq_ciu0_lock, flags); |
145 | * A read lock is used here to make sure only one core is ever | ||
146 | * updating the CIU enable bits at a time. During an enable | ||
147 | * the cores don't interfere with each other. During a disable | ||
148 | * the write lock stops any enables that might cause a | ||
149 | * problem. | ||
150 | */ | ||
151 | read_lock_irqsave(&octeon_irq_ciu0_rwlock, flags); | ||
152 | en0 = cvmx_read_csr(CVMX_CIU_INTX_EN0(coreid * 2)); | 141 | en0 = cvmx_read_csr(CVMX_CIU_INTX_EN0(coreid * 2)); |
153 | en0 |= 1ull << bit; | 142 | en0 |= 1ull << bit; |
154 | cvmx_write_csr(CVMX_CIU_INTX_EN0(coreid * 2), en0); | 143 | cvmx_write_csr(CVMX_CIU_INTX_EN0(coreid * 2), en0); |
155 | cvmx_read_csr(CVMX_CIU_INTX_EN0(coreid * 2)); | 144 | cvmx_read_csr(CVMX_CIU_INTX_EN0(coreid * 2)); |
156 | read_unlock_irqrestore(&octeon_irq_ciu0_rwlock, flags); | 145 | raw_spin_unlock_irqrestore(&octeon_irq_ciu0_lock, flags); |
157 | } | 146 | } |
158 | 147 | ||
159 | static void octeon_irq_ciu0_disable(unsigned int irq) | 148 | static void octeon_irq_ciu0_disable(unsigned int irq) |
@@ -162,7 +151,7 @@ static void octeon_irq_ciu0_disable(unsigned int irq) | |||
162 | unsigned long flags; | 151 | unsigned long flags; |
163 | uint64_t en0; | 152 | uint64_t en0; |
164 | int cpu; | 153 | int cpu; |
165 | write_lock_irqsave(&octeon_irq_ciu0_rwlock, flags); | 154 | raw_spin_lock_irqsave(&octeon_irq_ciu0_lock, flags); |
166 | for_each_online_cpu(cpu) { | 155 | for_each_online_cpu(cpu) { |
167 | int coreid = octeon_coreid_for_cpu(cpu); | 156 | int coreid = octeon_coreid_for_cpu(cpu); |
168 | en0 = cvmx_read_csr(CVMX_CIU_INTX_EN0(coreid * 2)); | 157 | en0 = cvmx_read_csr(CVMX_CIU_INTX_EN0(coreid * 2)); |
@@ -174,7 +163,7 @@ static void octeon_irq_ciu0_disable(unsigned int irq) | |||
174 | * of them are done. | 163 | * of them are done. |
175 | */ | 164 | */ |
176 | cvmx_read_csr(CVMX_CIU_INTX_EN0(cvmx_get_core_num() * 2)); | 165 | cvmx_read_csr(CVMX_CIU_INTX_EN0(cvmx_get_core_num() * 2)); |
177 | write_unlock_irqrestore(&octeon_irq_ciu0_rwlock, flags); | 166 | raw_spin_unlock_irqrestore(&octeon_irq_ciu0_lock, flags); |
178 | } | 167 | } |
179 | 168 | ||
180 | /* | 169 | /* |
@@ -193,7 +182,7 @@ static void octeon_irq_ciu0_enable_v2(unsigned int irq) | |||
193 | * Disable the irq on the current core for chips that have the EN*_W1{S,C} | 182 | * Disable the irq on the current core for chips that have the EN*_W1{S,C} |
194 | * registers. | 183 | * registers. |
195 | */ | 184 | */ |
196 | static void octeon_irq_ciu0_disable_v2(unsigned int irq) | 185 | static void octeon_irq_ciu0_ack_v2(unsigned int irq) |
197 | { | 186 | { |
198 | int index = cvmx_get_core_num() * 2; | 187 | int index = cvmx_get_core_num() * 2; |
199 | u64 mask = 1ull << (irq - OCTEON_IRQ_WORKQ0); | 188 | u64 mask = 1ull << (irq - OCTEON_IRQ_WORKQ0); |
@@ -202,6 +191,43 @@ static void octeon_irq_ciu0_disable_v2(unsigned int irq) | |||
202 | } | 191 | } |
203 | 192 | ||
204 | /* | 193 | /* |
194 | * CIU timer type interrupts must be acknoleged by writing a '1' bit | ||
195 | * to their sum0 bit. | ||
196 | */ | ||
197 | static void octeon_irq_ciu0_timer_ack(unsigned int irq) | ||
198 | { | ||
199 | int index = cvmx_get_core_num() * 2; | ||
200 | uint64_t mask = 1ull << (irq - OCTEON_IRQ_WORKQ0); | ||
201 | cvmx_write_csr(CVMX_CIU_INTX_SUM0(index), mask); | ||
202 | } | ||
203 | |||
204 | static void octeon_irq_ciu0_timer_ack_v1(unsigned int irq) | ||
205 | { | ||
206 | octeon_irq_ciu0_timer_ack(irq); | ||
207 | octeon_irq_ciu0_ack(irq); | ||
208 | } | ||
209 | |||
210 | static void octeon_irq_ciu0_timer_ack_v2(unsigned int irq) | ||
211 | { | ||
212 | octeon_irq_ciu0_timer_ack(irq); | ||
213 | octeon_irq_ciu0_ack_v2(irq); | ||
214 | } | ||
215 | |||
216 | /* | ||
217 | * Enable the irq on the current core for chips that have the EN*_W1{S,C} | ||
218 | * registers. | ||
219 | */ | ||
220 | static void octeon_irq_ciu0_eoi_v2(unsigned int irq) | ||
221 | { | ||
222 | struct irq_desc *desc = irq_desc + irq; | ||
223 | int index = cvmx_get_core_num() * 2; | ||
224 | u64 mask = 1ull << (irq - OCTEON_IRQ_WORKQ0); | ||
225 | |||
226 | if ((desc->status & IRQ_DISABLED) == 0) | ||
227 | cvmx_write_csr(CVMX_CIU_INTX_EN0_W1S(index), mask); | ||
228 | } | ||
229 | |||
230 | /* | ||
205 | * Disable the irq on the all cores for chips that have the EN*_W1{S,C} | 231 | * Disable the irq on the all cores for chips that have the EN*_W1{S,C} |
206 | * registers. | 232 | * registers. |
207 | */ | 233 | */ |
@@ -223,7 +249,7 @@ static int octeon_irq_ciu0_set_affinity(unsigned int irq, const struct cpumask * | |||
223 | unsigned long flags; | 249 | unsigned long flags; |
224 | int bit = irq - OCTEON_IRQ_WORKQ0; /* Bit 0-63 of EN0 */ | 250 | int bit = irq - OCTEON_IRQ_WORKQ0; /* Bit 0-63 of EN0 */ |
225 | 251 | ||
226 | write_lock_irqsave(&octeon_irq_ciu0_rwlock, flags); | 252 | raw_spin_lock_irqsave(&octeon_irq_ciu0_lock, flags); |
227 | for_each_online_cpu(cpu) { | 253 | for_each_online_cpu(cpu) { |
228 | int coreid = octeon_coreid_for_cpu(cpu); | 254 | int coreid = octeon_coreid_for_cpu(cpu); |
229 | uint64_t en0 = | 255 | uint64_t en0 = |
@@ -239,7 +265,7 @@ static int octeon_irq_ciu0_set_affinity(unsigned int irq, const struct cpumask * | |||
239 | * of them are done. | 265 | * of them are done. |
240 | */ | 266 | */ |
241 | cvmx_read_csr(CVMX_CIU_INTX_EN0(cvmx_get_core_num() * 2)); | 267 | cvmx_read_csr(CVMX_CIU_INTX_EN0(cvmx_get_core_num() * 2)); |
242 | write_unlock_irqrestore(&octeon_irq_ciu0_rwlock, flags); | 268 | raw_spin_unlock_irqrestore(&octeon_irq_ciu0_lock, flags); |
243 | 269 | ||
244 | return 0; | 270 | return 0; |
245 | } | 271 | } |
@@ -272,8 +298,8 @@ static struct irq_chip octeon_irq_chip_ciu0_v2 = { | |||
272 | .name = "CIU0", | 298 | .name = "CIU0", |
273 | .enable = octeon_irq_ciu0_enable_v2, | 299 | .enable = octeon_irq_ciu0_enable_v2, |
274 | .disable = octeon_irq_ciu0_disable_all_v2, | 300 | .disable = octeon_irq_ciu0_disable_all_v2, |
275 | .ack = octeon_irq_ciu0_disable_v2, | 301 | .ack = octeon_irq_ciu0_ack_v2, |
276 | .eoi = octeon_irq_ciu0_enable_v2, | 302 | .eoi = octeon_irq_ciu0_eoi_v2, |
277 | #ifdef CONFIG_SMP | 303 | #ifdef CONFIG_SMP |
278 | .set_affinity = octeon_irq_ciu0_set_affinity_v2, | 304 | .set_affinity = octeon_irq_ciu0_set_affinity_v2, |
279 | #endif | 305 | #endif |
@@ -290,6 +316,28 @@ static struct irq_chip octeon_irq_chip_ciu0 = { | |||
290 | #endif | 316 | #endif |
291 | }; | 317 | }; |
292 | 318 | ||
319 | static struct irq_chip octeon_irq_chip_ciu0_timer_v2 = { | ||
320 | .name = "CIU0-T", | ||
321 | .enable = octeon_irq_ciu0_enable_v2, | ||
322 | .disable = octeon_irq_ciu0_disable_all_v2, | ||
323 | .ack = octeon_irq_ciu0_timer_ack_v2, | ||
324 | .eoi = octeon_irq_ciu0_eoi_v2, | ||
325 | #ifdef CONFIG_SMP | ||
326 | .set_affinity = octeon_irq_ciu0_set_affinity_v2, | ||
327 | #endif | ||
328 | }; | ||
329 | |||
330 | static struct irq_chip octeon_irq_chip_ciu0_timer = { | ||
331 | .name = "CIU0-T", | ||
332 | .enable = octeon_irq_ciu0_enable, | ||
333 | .disable = octeon_irq_ciu0_disable, | ||
334 | .ack = octeon_irq_ciu0_timer_ack_v1, | ||
335 | .eoi = octeon_irq_ciu0_eoi, | ||
336 | #ifdef CONFIG_SMP | ||
337 | .set_affinity = octeon_irq_ciu0_set_affinity, | ||
338 | #endif | ||
339 | }; | ||
340 | |||
293 | 341 | ||
294 | static void octeon_irq_ciu1_ack(unsigned int irq) | 342 | static void octeon_irq_ciu1_ack(unsigned int irq) |
295 | { | 343 | { |
@@ -322,19 +370,12 @@ static void octeon_irq_ciu1_enable(unsigned int irq) | |||
322 | uint64_t en1; | 370 | uint64_t en1; |
323 | int bit = irq - OCTEON_IRQ_WDOG0; /* Bit 0-63 of EN1 */ | 371 | int bit = irq - OCTEON_IRQ_WDOG0; /* Bit 0-63 of EN1 */ |
324 | 372 | ||
325 | /* | 373 | raw_spin_lock_irqsave(&octeon_irq_ciu1_lock, flags); |
326 | * A read lock is used here to make sure only one core is ever | ||
327 | * updating the CIU enable bits at a time. During an enable | ||
328 | * the cores don't interfere with each other. During a disable | ||
329 | * the write lock stops any enables that might cause a | ||
330 | * problem. | ||
331 | */ | ||
332 | read_lock_irqsave(&octeon_irq_ciu1_rwlock, flags); | ||
333 | en1 = cvmx_read_csr(CVMX_CIU_INTX_EN1(coreid * 2 + 1)); | 374 | en1 = cvmx_read_csr(CVMX_CIU_INTX_EN1(coreid * 2 + 1)); |
334 | en1 |= 1ull << bit; | 375 | en1 |= 1ull << bit; |
335 | cvmx_write_csr(CVMX_CIU_INTX_EN1(coreid * 2 + 1), en1); | 376 | cvmx_write_csr(CVMX_CIU_INTX_EN1(coreid * 2 + 1), en1); |
336 | cvmx_read_csr(CVMX_CIU_INTX_EN1(coreid * 2 + 1)); | 377 | cvmx_read_csr(CVMX_CIU_INTX_EN1(coreid * 2 + 1)); |
337 | read_unlock_irqrestore(&octeon_irq_ciu1_rwlock, flags); | 378 | raw_spin_unlock_irqrestore(&octeon_irq_ciu1_lock, flags); |
338 | } | 379 | } |
339 | 380 | ||
340 | static void octeon_irq_ciu1_disable(unsigned int irq) | 381 | static void octeon_irq_ciu1_disable(unsigned int irq) |
@@ -343,7 +384,7 @@ static void octeon_irq_ciu1_disable(unsigned int irq) | |||
343 | unsigned long flags; | 384 | unsigned long flags; |
344 | uint64_t en1; | 385 | uint64_t en1; |
345 | int cpu; | 386 | int cpu; |
346 | write_lock_irqsave(&octeon_irq_ciu1_rwlock, flags); | 387 | raw_spin_lock_irqsave(&octeon_irq_ciu1_lock, flags); |
347 | for_each_online_cpu(cpu) { | 388 | for_each_online_cpu(cpu) { |
348 | int coreid = octeon_coreid_for_cpu(cpu); | 389 | int coreid = octeon_coreid_for_cpu(cpu); |
349 | en1 = cvmx_read_csr(CVMX_CIU_INTX_EN1(coreid * 2 + 1)); | 390 | en1 = cvmx_read_csr(CVMX_CIU_INTX_EN1(coreid * 2 + 1)); |
@@ -355,7 +396,7 @@ static void octeon_irq_ciu1_disable(unsigned int irq) | |||
355 | * of them are done. | 396 | * of them are done. |
356 | */ | 397 | */ |
357 | cvmx_read_csr(CVMX_CIU_INTX_EN1(cvmx_get_core_num() * 2 + 1)); | 398 | cvmx_read_csr(CVMX_CIU_INTX_EN1(cvmx_get_core_num() * 2 + 1)); |
358 | write_unlock_irqrestore(&octeon_irq_ciu1_rwlock, flags); | 399 | raw_spin_unlock_irqrestore(&octeon_irq_ciu1_lock, flags); |
359 | } | 400 | } |
360 | 401 | ||
361 | /* | 402 | /* |
@@ -374,7 +415,7 @@ static void octeon_irq_ciu1_enable_v2(unsigned int irq) | |||
374 | * Disable the irq on the current core for chips that have the EN*_W1{S,C} | 415 | * Disable the irq on the current core for chips that have the EN*_W1{S,C} |
375 | * registers. | 416 | * registers. |
376 | */ | 417 | */ |
377 | static void octeon_irq_ciu1_disable_v2(unsigned int irq) | 418 | static void octeon_irq_ciu1_ack_v2(unsigned int irq) |
378 | { | 419 | { |
379 | int index = cvmx_get_core_num() * 2 + 1; | 420 | int index = cvmx_get_core_num() * 2 + 1; |
380 | u64 mask = 1ull << (irq - OCTEON_IRQ_WDOG0); | 421 | u64 mask = 1ull << (irq - OCTEON_IRQ_WDOG0); |
@@ -383,6 +424,20 @@ static void octeon_irq_ciu1_disable_v2(unsigned int irq) | |||
383 | } | 424 | } |
384 | 425 | ||
385 | /* | 426 | /* |
427 | * Enable the irq on the current core for chips that have the EN*_W1{S,C} | ||
428 | * registers. | ||
429 | */ | ||
430 | static void octeon_irq_ciu1_eoi_v2(unsigned int irq) | ||
431 | { | ||
432 | struct irq_desc *desc = irq_desc + irq; | ||
433 | int index = cvmx_get_core_num() * 2 + 1; | ||
434 | u64 mask = 1ull << (irq - OCTEON_IRQ_WDOG0); | ||
435 | |||
436 | if ((desc->status & IRQ_DISABLED) == 0) | ||
437 | cvmx_write_csr(CVMX_CIU_INTX_EN1_W1S(index), mask); | ||
438 | } | ||
439 | |||
440 | /* | ||
386 | * Disable the irq on the all cores for chips that have the EN*_W1{S,C} | 441 | * Disable the irq on the all cores for chips that have the EN*_W1{S,C} |
387 | * registers. | 442 | * registers. |
388 | */ | 443 | */ |
@@ -405,7 +460,7 @@ static int octeon_irq_ciu1_set_affinity(unsigned int irq, | |||
405 | unsigned long flags; | 460 | unsigned long flags; |
406 | int bit = irq - OCTEON_IRQ_WDOG0; /* Bit 0-63 of EN1 */ | 461 | int bit = irq - OCTEON_IRQ_WDOG0; /* Bit 0-63 of EN1 */ |
407 | 462 | ||
408 | write_lock_irqsave(&octeon_irq_ciu1_rwlock, flags); | 463 | raw_spin_lock_irqsave(&octeon_irq_ciu1_lock, flags); |
409 | for_each_online_cpu(cpu) { | 464 | for_each_online_cpu(cpu) { |
410 | int coreid = octeon_coreid_for_cpu(cpu); | 465 | int coreid = octeon_coreid_for_cpu(cpu); |
411 | uint64_t en1 = | 466 | uint64_t en1 = |
@@ -422,7 +477,7 @@ static int octeon_irq_ciu1_set_affinity(unsigned int irq, | |||
422 | * of them are done. | 477 | * of them are done. |
423 | */ | 478 | */ |
424 | cvmx_read_csr(CVMX_CIU_INTX_EN1(cvmx_get_core_num() * 2 + 1)); | 479 | cvmx_read_csr(CVMX_CIU_INTX_EN1(cvmx_get_core_num() * 2 + 1)); |
425 | write_unlock_irqrestore(&octeon_irq_ciu1_rwlock, flags); | 480 | raw_spin_unlock_irqrestore(&octeon_irq_ciu1_lock, flags); |
426 | 481 | ||
427 | return 0; | 482 | return 0; |
428 | } | 483 | } |
@@ -455,8 +510,8 @@ static struct irq_chip octeon_irq_chip_ciu1_v2 = { | |||
455 | .name = "CIU0", | 510 | .name = "CIU0", |
456 | .enable = octeon_irq_ciu1_enable_v2, | 511 | .enable = octeon_irq_ciu1_enable_v2, |
457 | .disable = octeon_irq_ciu1_disable_all_v2, | 512 | .disable = octeon_irq_ciu1_disable_all_v2, |
458 | .ack = octeon_irq_ciu1_disable_v2, | 513 | .ack = octeon_irq_ciu1_ack_v2, |
459 | .eoi = octeon_irq_ciu1_enable_v2, | 514 | .eoi = octeon_irq_ciu1_eoi_v2, |
460 | #ifdef CONFIG_SMP | 515 | #ifdef CONFIG_SMP |
461 | .set_affinity = octeon_irq_ciu1_set_affinity_v2, | 516 | .set_affinity = octeon_irq_ciu1_set_affinity_v2, |
462 | #endif | 517 | #endif |
@@ -475,6 +530,8 @@ static struct irq_chip octeon_irq_chip_ciu1 = { | |||
475 | 530 | ||
476 | #ifdef CONFIG_PCI_MSI | 531 | #ifdef CONFIG_PCI_MSI |
477 | 532 | ||
533 | static DEFINE_RAW_SPINLOCK(octeon_irq_msi_lock); | ||
534 | |||
478 | static void octeon_irq_msi_ack(unsigned int irq) | 535 | static void octeon_irq_msi_ack(unsigned int irq) |
479 | { | 536 | { |
480 | if (!octeon_has_feature(OCTEON_FEATURE_PCIE)) { | 537 | if (!octeon_has_feature(OCTEON_FEATURE_PCIE)) { |
@@ -515,12 +572,12 @@ static void octeon_irq_msi_enable(unsigned int irq) | |||
515 | */ | 572 | */ |
516 | uint64_t en; | 573 | uint64_t en; |
517 | unsigned long flags; | 574 | unsigned long flags; |
518 | spin_lock_irqsave(&octeon_irq_msi_lock, flags); | 575 | raw_spin_lock_irqsave(&octeon_irq_msi_lock, flags); |
519 | en = cvmx_read_csr(CVMX_PEXP_NPEI_MSI_ENB0); | 576 | en = cvmx_read_csr(CVMX_PEXP_NPEI_MSI_ENB0); |
520 | en |= 1ull << (irq - OCTEON_IRQ_MSI_BIT0); | 577 | en |= 1ull << (irq - OCTEON_IRQ_MSI_BIT0); |
521 | cvmx_write_csr(CVMX_PEXP_NPEI_MSI_ENB0, en); | 578 | cvmx_write_csr(CVMX_PEXP_NPEI_MSI_ENB0, en); |
522 | cvmx_read_csr(CVMX_PEXP_NPEI_MSI_ENB0); | 579 | cvmx_read_csr(CVMX_PEXP_NPEI_MSI_ENB0); |
523 | spin_unlock_irqrestore(&octeon_irq_msi_lock, flags); | 580 | raw_spin_unlock_irqrestore(&octeon_irq_msi_lock, flags); |
524 | } | 581 | } |
525 | } | 582 | } |
526 | 583 | ||
@@ -537,12 +594,12 @@ static void octeon_irq_msi_disable(unsigned int irq) | |||
537 | */ | 594 | */ |
538 | uint64_t en; | 595 | uint64_t en; |
539 | unsigned long flags; | 596 | unsigned long flags; |
540 | spin_lock_irqsave(&octeon_irq_msi_lock, flags); | 597 | raw_spin_lock_irqsave(&octeon_irq_msi_lock, flags); |
541 | en = cvmx_read_csr(CVMX_PEXP_NPEI_MSI_ENB0); | 598 | en = cvmx_read_csr(CVMX_PEXP_NPEI_MSI_ENB0); |
542 | en &= ~(1ull << (irq - OCTEON_IRQ_MSI_BIT0)); | 599 | en &= ~(1ull << (irq - OCTEON_IRQ_MSI_BIT0)); |
543 | cvmx_write_csr(CVMX_PEXP_NPEI_MSI_ENB0, en); | 600 | cvmx_write_csr(CVMX_PEXP_NPEI_MSI_ENB0, en); |
544 | cvmx_read_csr(CVMX_PEXP_NPEI_MSI_ENB0); | 601 | cvmx_read_csr(CVMX_PEXP_NPEI_MSI_ENB0); |
545 | spin_unlock_irqrestore(&octeon_irq_msi_lock, flags); | 602 | raw_spin_unlock_irqrestore(&octeon_irq_msi_lock, flags); |
546 | } | 603 | } |
547 | } | 604 | } |
548 | 605 | ||
@@ -559,6 +616,7 @@ void __init arch_init_irq(void) | |||
559 | { | 616 | { |
560 | int irq; | 617 | int irq; |
561 | struct irq_chip *chip0; | 618 | struct irq_chip *chip0; |
619 | struct irq_chip *chip0_timer; | ||
562 | struct irq_chip *chip1; | 620 | struct irq_chip *chip1; |
563 | 621 | ||
564 | #ifdef CONFIG_SMP | 622 | #ifdef CONFIG_SMP |
@@ -574,9 +632,11 @@ void __init arch_init_irq(void) | |||
574 | OCTEON_IS_MODEL(OCTEON_CN56XX_PASS2_X) || | 632 | OCTEON_IS_MODEL(OCTEON_CN56XX_PASS2_X) || |
575 | OCTEON_IS_MODEL(OCTEON_CN52XX_PASS2_X)) { | 633 | OCTEON_IS_MODEL(OCTEON_CN52XX_PASS2_X)) { |
576 | chip0 = &octeon_irq_chip_ciu0_v2; | 634 | chip0 = &octeon_irq_chip_ciu0_v2; |
635 | chip0_timer = &octeon_irq_chip_ciu0_timer_v2; | ||
577 | chip1 = &octeon_irq_chip_ciu1_v2; | 636 | chip1 = &octeon_irq_chip_ciu1_v2; |
578 | } else { | 637 | } else { |
579 | chip0 = &octeon_irq_chip_ciu0; | 638 | chip0 = &octeon_irq_chip_ciu0; |
639 | chip0_timer = &octeon_irq_chip_ciu0_timer; | ||
580 | chip1 = &octeon_irq_chip_ciu1; | 640 | chip1 = &octeon_irq_chip_ciu1; |
581 | } | 641 | } |
582 | 642 | ||
@@ -590,7 +650,21 @@ void __init arch_init_irq(void) | |||
590 | 650 | ||
591 | /* 24 - 87 CIU_INT_SUM0 */ | 651 | /* 24 - 87 CIU_INT_SUM0 */ |
592 | for (irq = OCTEON_IRQ_WORKQ0; irq <= OCTEON_IRQ_BOOTDMA; irq++) { | 652 | for (irq = OCTEON_IRQ_WORKQ0; irq <= OCTEON_IRQ_BOOTDMA; irq++) { |
593 | set_irq_chip_and_handler(irq, chip0, handle_percpu_irq); | 653 | switch (irq) { |
654 | case OCTEON_IRQ_GMX_DRP0: | ||
655 | case OCTEON_IRQ_GMX_DRP1: | ||
656 | case OCTEON_IRQ_IPD_DRP: | ||
657 | case OCTEON_IRQ_KEY_ZERO: | ||
658 | case OCTEON_IRQ_TIMER0: | ||
659 | case OCTEON_IRQ_TIMER1: | ||
660 | case OCTEON_IRQ_TIMER2: | ||
661 | case OCTEON_IRQ_TIMER3: | ||
662 | set_irq_chip_and_handler(irq, chip0_timer, handle_percpu_irq); | ||
663 | break; | ||
664 | default: | ||
665 | set_irq_chip_and_handler(irq, chip0, handle_percpu_irq); | ||
666 | break; | ||
667 | } | ||
594 | } | 668 | } |
595 | 669 | ||
596 | /* 88 - 151 CIU_INT_SUM1 */ | 670 | /* 88 - 151 CIU_INT_SUM1 */ |
diff --git a/arch/mips/cavium-octeon/octeon-platform.c b/arch/mips/cavium-octeon/octeon-platform.c index be711dd2d918..62ac30eef5e8 100644 --- a/arch/mips/cavium-octeon/octeon-platform.c +++ b/arch/mips/cavium-octeon/octeon-platform.c | |||
@@ -9,6 +9,7 @@ | |||
9 | 9 | ||
10 | #include <linux/init.h> | 10 | #include <linux/init.h> |
11 | #include <linux/irq.h> | 11 | #include <linux/irq.h> |
12 | #include <linux/i2c.h> | ||
12 | #include <linux/module.h> | 13 | #include <linux/module.h> |
13 | #include <linux/platform_device.h> | 14 | #include <linux/platform_device.h> |
14 | 15 | ||
@@ -159,6 +160,178 @@ out: | |||
159 | } | 160 | } |
160 | device_initcall(octeon_rng_device_init); | 161 | device_initcall(octeon_rng_device_init); |
161 | 162 | ||
163 | static struct i2c_board_info __initdata octeon_i2c_devices[] = { | ||
164 | { | ||
165 | I2C_BOARD_INFO("ds1337", 0x68), | ||
166 | }, | ||
167 | }; | ||
168 | |||
169 | static int __init octeon_i2c_devices_init(void) | ||
170 | { | ||
171 | return i2c_register_board_info(0, octeon_i2c_devices, | ||
172 | ARRAY_SIZE(octeon_i2c_devices)); | ||
173 | } | ||
174 | arch_initcall(octeon_i2c_devices_init); | ||
175 | |||
176 | #define OCTEON_I2C_IO_BASE 0x1180000001000ull | ||
177 | #define OCTEON_I2C_IO_UNIT_OFFSET 0x200 | ||
178 | |||
179 | static struct octeon_i2c_data octeon_i2c_data[2]; | ||
180 | |||
181 | static int __init octeon_i2c_device_init(void) | ||
182 | { | ||
183 | struct platform_device *pd; | ||
184 | int ret = 0; | ||
185 | int port, num_ports; | ||
186 | |||
187 | struct resource i2c_resources[] = { | ||
188 | { | ||
189 | .flags = IORESOURCE_MEM, | ||
190 | }, { | ||
191 | .flags = IORESOURCE_IRQ, | ||
192 | } | ||
193 | }; | ||
194 | |||
195 | if (OCTEON_IS_MODEL(OCTEON_CN56XX) || OCTEON_IS_MODEL(OCTEON_CN52XX)) | ||
196 | num_ports = 2; | ||
197 | else | ||
198 | num_ports = 1; | ||
199 | |||
200 | for (port = 0; port < num_ports; port++) { | ||
201 | octeon_i2c_data[port].sys_freq = octeon_get_clock_rate(); | ||
202 | /*FIXME: should be examined. At the moment is set for 100Khz */ | ||
203 | octeon_i2c_data[port].i2c_freq = 100000; | ||
204 | |||
205 | pd = platform_device_alloc("i2c-octeon", port); | ||
206 | if (!pd) { | ||
207 | ret = -ENOMEM; | ||
208 | goto out; | ||
209 | } | ||
210 | |||
211 | pd->dev.platform_data = octeon_i2c_data + port; | ||
212 | |||
213 | i2c_resources[0].start = | ||
214 | OCTEON_I2C_IO_BASE + (port * OCTEON_I2C_IO_UNIT_OFFSET); | ||
215 | i2c_resources[0].end = i2c_resources[0].start + 0x1f; | ||
216 | switch (port) { | ||
217 | case 0: | ||
218 | i2c_resources[1].start = OCTEON_IRQ_TWSI; | ||
219 | i2c_resources[1].end = OCTEON_IRQ_TWSI; | ||
220 | break; | ||
221 | case 1: | ||
222 | i2c_resources[1].start = OCTEON_IRQ_TWSI2; | ||
223 | i2c_resources[1].end = OCTEON_IRQ_TWSI2; | ||
224 | break; | ||
225 | default: | ||
226 | BUG(); | ||
227 | } | ||
228 | |||
229 | ret = platform_device_add_resources(pd, | ||
230 | i2c_resources, | ||
231 | ARRAY_SIZE(i2c_resources)); | ||
232 | if (ret) | ||
233 | goto fail; | ||
234 | |||
235 | ret = platform_device_add(pd); | ||
236 | if (ret) | ||
237 | goto fail; | ||
238 | } | ||
239 | return ret; | ||
240 | fail: | ||
241 | platform_device_put(pd); | ||
242 | out: | ||
243 | return ret; | ||
244 | } | ||
245 | device_initcall(octeon_i2c_device_init); | ||
246 | |||
247 | /* Octeon SMI/MDIO interface. */ | ||
248 | static int __init octeon_mdiobus_device_init(void) | ||
249 | { | ||
250 | struct platform_device *pd; | ||
251 | int ret = 0; | ||
252 | |||
253 | if (octeon_is_simulation()) | ||
254 | return 0; /* No mdio in the simulator. */ | ||
255 | |||
256 | /* The bus number is the platform_device id. */ | ||
257 | pd = platform_device_alloc("mdio-octeon", 0); | ||
258 | if (!pd) { | ||
259 | ret = -ENOMEM; | ||
260 | goto out; | ||
261 | } | ||
262 | |||
263 | ret = platform_device_add(pd); | ||
264 | if (ret) | ||
265 | goto fail; | ||
266 | |||
267 | return ret; | ||
268 | fail: | ||
269 | platform_device_put(pd); | ||
270 | |||
271 | out: | ||
272 | return ret; | ||
273 | |||
274 | } | ||
275 | device_initcall(octeon_mdiobus_device_init); | ||
276 | |||
277 | /* Octeon mgmt port Ethernet interface. */ | ||
278 | static int __init octeon_mgmt_device_init(void) | ||
279 | { | ||
280 | struct platform_device *pd; | ||
281 | int ret = 0; | ||
282 | int port, num_ports; | ||
283 | |||
284 | struct resource mgmt_port_resource = { | ||
285 | .flags = IORESOURCE_IRQ, | ||
286 | .start = -1, | ||
287 | .end = -1 | ||
288 | }; | ||
289 | |||
290 | if (!OCTEON_IS_MODEL(OCTEON_CN56XX) && !OCTEON_IS_MODEL(OCTEON_CN52XX)) | ||
291 | return 0; | ||
292 | |||
293 | if (OCTEON_IS_MODEL(OCTEON_CN56XX)) | ||
294 | num_ports = 1; | ||
295 | else | ||
296 | num_ports = 2; | ||
297 | |||
298 | for (port = 0; port < num_ports; port++) { | ||
299 | pd = platform_device_alloc("octeon_mgmt", port); | ||
300 | if (!pd) { | ||
301 | ret = -ENOMEM; | ||
302 | goto out; | ||
303 | } | ||
304 | switch (port) { | ||
305 | case 0: | ||
306 | mgmt_port_resource.start = OCTEON_IRQ_MII0; | ||
307 | break; | ||
308 | case 1: | ||
309 | mgmt_port_resource.start = OCTEON_IRQ_MII1; | ||
310 | break; | ||
311 | default: | ||
312 | BUG(); | ||
313 | } | ||
314 | mgmt_port_resource.end = mgmt_port_resource.start; | ||
315 | |||
316 | ret = platform_device_add_resources(pd, &mgmt_port_resource, 1); | ||
317 | |||
318 | if (ret) | ||
319 | goto fail; | ||
320 | |||
321 | ret = platform_device_add(pd); | ||
322 | if (ret) | ||
323 | goto fail; | ||
324 | } | ||
325 | return ret; | ||
326 | fail: | ||
327 | platform_device_put(pd); | ||
328 | |||
329 | out: | ||
330 | return ret; | ||
331 | |||
332 | } | ||
333 | device_initcall(octeon_mgmt_device_init); | ||
334 | |||
162 | MODULE_AUTHOR("David Daney <ddaney@caviumnetworks.com>"); | 335 | MODULE_AUTHOR("David Daney <ddaney@caviumnetworks.com>"); |
163 | MODULE_LICENSE("GPL"); | 336 | MODULE_LICENSE("GPL"); |
164 | MODULE_DESCRIPTION("Platform driver for Octeon SOC"); | 337 | MODULE_DESCRIPTION("Platform driver for Octeon SOC"); |
diff --git a/arch/mips/cavium-octeon/setup.c b/arch/mips/cavium-octeon/setup.c index b321d3b16877..9a06fa9f9f0c 100644 --- a/arch/mips/cavium-octeon/setup.c +++ b/arch/mips/cavium-octeon/setup.c | |||
@@ -45,9 +45,6 @@ extern struct plat_smp_ops octeon_smp_ops; | |||
45 | extern void pci_console_init(const char *arg); | 45 | extern void pci_console_init(const char *arg); |
46 | #endif | 46 | #endif |
47 | 47 | ||
48 | #ifdef CONFIG_CAVIUM_RESERVE32 | ||
49 | extern uint64_t octeon_reserve32_memory; | ||
50 | #endif | ||
51 | static unsigned long long MAX_MEMORY = 512ull << 20; | 48 | static unsigned long long MAX_MEMORY = 512ull << 20; |
52 | 49 | ||
53 | struct octeon_boot_descriptor *octeon_boot_desc_ptr; | 50 | struct octeon_boot_descriptor *octeon_boot_desc_ptr; |
@@ -186,54 +183,6 @@ void octeon_check_cpu_bist(void) | |||
186 | write_octeon_c0_dcacheerr(0); | 183 | write_octeon_c0_dcacheerr(0); |
187 | } | 184 | } |
188 | 185 | ||
189 | #ifdef CONFIG_CAVIUM_RESERVE32_USE_WIRED_TLB | ||
190 | /** | ||
191 | * Called on every core to setup the wired tlb entry needed | ||
192 | * if CONFIG_CAVIUM_RESERVE32_USE_WIRED_TLB is set. | ||
193 | * | ||
194 | */ | ||
195 | static void octeon_hal_setup_per_cpu_reserved32(void *unused) | ||
196 | { | ||
197 | /* | ||
198 | * The config has selected to wire the reserve32 memory for all | ||
199 | * userspace applications. We need to put a wired TLB entry in for each | ||
200 | * 512MB of reserve32 memory. We only handle double 256MB pages here, | ||
201 | * so reserve32 must be multiple of 512MB. | ||
202 | */ | ||
203 | uint32_t size = CONFIG_CAVIUM_RESERVE32; | ||
204 | uint32_t entrylo0 = | ||
205 | 0x7 | ((octeon_reserve32_memory & ((1ul << 40) - 1)) >> 6); | ||
206 | uint32_t entrylo1 = entrylo0 + (256 << 14); | ||
207 | uint32_t entryhi = (0x80000000UL - (CONFIG_CAVIUM_RESERVE32 << 20)); | ||
208 | while (size >= 512) { | ||
209 | #if 0 | ||
210 | pr_info("CPU%d: Adding double wired TLB entry for 0x%lx\n", | ||
211 | smp_processor_id(), entryhi); | ||
212 | #endif | ||
213 | add_wired_entry(entrylo0, entrylo1, entryhi, PM_256M); | ||
214 | entrylo0 += 512 << 14; | ||
215 | entrylo1 += 512 << 14; | ||
216 | entryhi += 512 << 20; | ||
217 | size -= 512; | ||
218 | } | ||
219 | } | ||
220 | #endif /* CONFIG_CAVIUM_RESERVE32_USE_WIRED_TLB */ | ||
221 | |||
222 | /** | ||
223 | * Called to release the named block which was used to made sure | ||
224 | * that nobody used the memory for something else during | ||
225 | * init. Now we'll free it so userspace apps can use this | ||
226 | * memory region with bootmem_alloc. | ||
227 | * | ||
228 | * This function is called only once from prom_free_prom_memory(). | ||
229 | */ | ||
230 | void octeon_hal_setup_reserved32(void) | ||
231 | { | ||
232 | #ifdef CONFIG_CAVIUM_RESERVE32_USE_WIRED_TLB | ||
233 | on_each_cpu(octeon_hal_setup_per_cpu_reserved32, NULL, 0, 1); | ||
234 | #endif | ||
235 | } | ||
236 | |||
237 | /** | 186 | /** |
238 | * Reboot Octeon | 187 | * Reboot Octeon |
239 | * | 188 | * |
@@ -294,18 +243,6 @@ static void octeon_halt(void) | |||
294 | octeon_kill_core(NULL); | 243 | octeon_kill_core(NULL); |
295 | } | 244 | } |
296 | 245 | ||
297 | #if 0 | ||
298 | /** | ||
299 | * Platform time init specifics. | ||
300 | * Returns | ||
301 | */ | ||
302 | void __init plat_time_init(void) | ||
303 | { | ||
304 | /* Nothing special here, but we are required to have one */ | ||
305 | } | ||
306 | |||
307 | #endif | ||
308 | |||
309 | /** | 246 | /** |
310 | * Handle all the error condition interrupts that might occur. | 247 | * Handle all the error condition interrupts that might occur. |
311 | * | 248 | * |
@@ -502,25 +439,13 @@ void __init prom_init(void) | |||
502 | * memory when it is getting memory from the | 439 | * memory when it is getting memory from the |
503 | * bootloader. Later, after the memory allocations are | 440 | * bootloader. Later, after the memory allocations are |
504 | * complete, the reserve32 will be freed. | 441 | * complete, the reserve32 will be freed. |
505 | */ | 442 | * |
506 | #ifdef CONFIG_CAVIUM_RESERVE32_USE_WIRED_TLB | ||
507 | if (CONFIG_CAVIUM_RESERVE32 & 0x1ff) | ||
508 | pr_err("CAVIUM_RESERVE32 isn't a multiple of 512MB. " | ||
509 | "This is required if CAVIUM_RESERVE32_USE_WIRED_TLB " | ||
510 | "is set\n"); | ||
511 | else | ||
512 | addr = cvmx_bootmem_phy_named_block_alloc(CONFIG_CAVIUM_RESERVE32 << 20, | ||
513 | 0, 0, 512 << 20, | ||
514 | "CAVIUM_RESERVE32", 0); | ||
515 | #else | ||
516 | /* | ||
517 | * Allocate memory for RESERVED32 aligned on 2MB boundary. This | 443 | * Allocate memory for RESERVED32 aligned on 2MB boundary. This |
518 | * is in case we later use hugetlb entries with it. | 444 | * is in case we later use hugetlb entries with it. |
519 | */ | 445 | */ |
520 | addr = cvmx_bootmem_phy_named_block_alloc(CONFIG_CAVIUM_RESERVE32 << 20, | 446 | addr = cvmx_bootmem_phy_named_block_alloc(CONFIG_CAVIUM_RESERVE32 << 20, |
521 | 0, 0, 2 << 20, | 447 | 0, 0, 2 << 20, |
522 | "CAVIUM_RESERVE32", 0); | 448 | "CAVIUM_RESERVE32", 0); |
523 | #endif | ||
524 | if (addr < 0) | 449 | if (addr < 0) |
525 | pr_err("Failed to allocate CAVIUM_RESERVE32 memory area\n"); | 450 | pr_err("Failed to allocate CAVIUM_RESERVE32 memory area\n"); |
526 | else | 451 | else |
@@ -817,9 +742,4 @@ void prom_free_prom_memory(void) | |||
817 | panic("Unable to request_irq(OCTEON_IRQ_RML)\n"); | 742 | panic("Unable to request_irq(OCTEON_IRQ_RML)\n"); |
818 | } | 743 | } |
819 | #endif | 744 | #endif |
820 | |||
821 | /* This call is here so that it is performed after any TLB | ||
822 | initializations. It needs to be after these in case the | ||
823 | CONFIG_CAVIUM_RESERVE32_USE_WIRED_TLB option is set */ | ||
824 | octeon_hal_setup_reserved32(); | ||
825 | } | 745 | } |
diff --git a/arch/mips/cavium-octeon/smp.c b/arch/mips/cavium-octeon/smp.c index c198efdf583e..6d99b9d8887d 100644 --- a/arch/mips/cavium-octeon/smp.c +++ b/arch/mips/cavium-octeon/smp.c | |||
@@ -279,14 +279,6 @@ static void octeon_cpu_die(unsigned int cpu) | |||
279 | uint32_t avail_coremask; | 279 | uint32_t avail_coremask; |
280 | struct cvmx_bootmem_named_block_desc *block_desc; | 280 | struct cvmx_bootmem_named_block_desc *block_desc; |
281 | 281 | ||
282 | #ifdef CONFIG_CAVIUM_OCTEON_WATCHDOG | ||
283 | /* Disable the watchdog */ | ||
284 | cvmx_ciu_wdogx_t ciu_wdog; | ||
285 | ciu_wdog.u64 = cvmx_read_csr(CVMX_CIU_WDOGX(cpu)); | ||
286 | ciu_wdog.s.mode = 0; | ||
287 | cvmx_write_csr(CVMX_CIU_WDOGX(cpu), ciu_wdog.u64); | ||
288 | #endif | ||
289 | |||
290 | while (per_cpu(cpu_state, cpu) != CPU_DEAD) | 282 | while (per_cpu(cpu_state, cpu) != CPU_DEAD) |
291 | cpu_relax(); | 283 | cpu_relax(); |
292 | 284 | ||
@@ -327,7 +319,7 @@ static void octeon_cpu_die(unsigned int cpu) | |||
327 | avail_coremask); | 319 | avail_coremask); |
328 | } | 320 | } |
329 | 321 | ||
330 | pr_info("Reset core %d. Available Coremask = %x \n", coreid, | 322 | pr_info("Reset core %d. Available Coremask = %x\n", coreid, |
331 | avail_coremask); | 323 | avail_coremask); |
332 | cvmx_write_csr(CVMX_CIU_PP_RST, 1 << coreid); | 324 | cvmx_write_csr(CVMX_CIU_PP_RST, 1 << coreid); |
333 | cvmx_write_csr(CVMX_CIU_PP_RST, 0); | 325 | cvmx_write_csr(CVMX_CIU_PP_RST, 0); |