diff options
Diffstat (limited to 'arch/mips/cavium-octeon')
-rw-r--r-- | arch/mips/cavium-octeon/.gitignore | 2 | ||||
-rw-r--r-- | arch/mips/cavium-octeon/Makefile | 16 | ||||
-rw-r--r-- | arch/mips/cavium-octeon/executive/cvmx-fpa.c | 183 | ||||
-rw-r--r-- | arch/mips/cavium-octeon/executive/cvmx-helper-fpa.c | 243 | ||||
-rw-r--r-- | arch/mips/cavium-octeon/octeon-irq.c | 399 | ||||
-rw-r--r-- | arch/mips/cavium-octeon/octeon-memcpy.S | 16 | ||||
-rw-r--r-- | arch/mips/cavium-octeon/octeon-platform.c | 699 | ||||
-rw-r--r-- | arch/mips/cavium-octeon/octeon_3xxx.dts | 571 | ||||
-rw-r--r-- | arch/mips/cavium-octeon/octeon_68xx.dts | 625 | ||||
-rw-r--r-- | arch/mips/cavium-octeon/serial.c | 134 | ||||
-rw-r--r-- | arch/mips/cavium-octeon/setup.c | 45 |
11 files changed, 2160 insertions, 773 deletions
diff --git a/arch/mips/cavium-octeon/.gitignore b/arch/mips/cavium-octeon/.gitignore new file mode 100644 index 00000000000..39c968605ff --- /dev/null +++ b/arch/mips/cavium-octeon/.gitignore | |||
@@ -0,0 +1,2 @@ | |||
1 | *.dtb.S | ||
2 | *.dtb | ||
diff --git a/arch/mips/cavium-octeon/Makefile b/arch/mips/cavium-octeon/Makefile index 19eb0434269..bc96e2908f1 100644 --- a/arch/mips/cavium-octeon/Makefile +++ b/arch/mips/cavium-octeon/Makefile | |||
@@ -9,9 +9,25 @@ | |||
9 | # Copyright (C) 2005-2009 Cavium Networks | 9 | # Copyright (C) 2005-2009 Cavium Networks |
10 | # | 10 | # |
11 | 11 | ||
12 | CFLAGS_octeon-platform.o = -I$(src)/../../../scripts/dtc/libfdt | ||
13 | CFLAGS_setup.o = -I$(src)/../../../scripts/dtc/libfdt | ||
14 | |||
12 | obj-y := cpu.o setup.o serial.o octeon-platform.o octeon-irq.o csrc-octeon.o | 15 | 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 | 16 | obj-y += dma-octeon.o flash_setup.o |
14 | obj-y += octeon-memcpy.o | 17 | obj-y += octeon-memcpy.o |
15 | obj-y += executive/ | 18 | obj-y += executive/ |
16 | 19 | ||
17 | obj-$(CONFIG_SMP) += smp.o | 20 | obj-$(CONFIG_SMP) += smp.o |
21 | |||
22 | DTS_FILES = octeon_3xxx.dts octeon_68xx.dts | ||
23 | DTB_FILES = $(patsubst %.dts, %.dtb, $(DTS_FILES)) | ||
24 | |||
25 | obj-y += $(patsubst %.dts, %.dtb.o, $(DTS_FILES)) | ||
26 | |||
27 | $(obj)/%.dtb: $(src)/%.dts FORCE | ||
28 | $(call if_changed_dep,dtc) | ||
29 | |||
30 | # Let's keep the .dtb files around in case we want to look at them. | ||
31 | .SECONDARY: $(addprefix $(obj)/, $(DTB_FILES)) | ||
32 | |||
33 | clean-files += $(DTB_FILES) $(patsubst %.dtb, %.dtb.S, $(DTB_FILES)) | ||
diff --git a/arch/mips/cavium-octeon/executive/cvmx-fpa.c b/arch/mips/cavium-octeon/executive/cvmx-fpa.c deleted file mode 100644 index ad44b8bd805..00000000000 --- a/arch/mips/cavium-octeon/executive/cvmx-fpa.c +++ /dev/null | |||
@@ -1,183 +0,0 @@ | |||
1 | /***********************license start*************** | ||
2 | * Author: Cavium Networks | ||
3 | * | ||
4 | * Contact: support@caviumnetworks.com | ||
5 | * This file is part of the OCTEON SDK | ||
6 | * | ||
7 | * Copyright (c) 2003-2008 Cavium Networks | ||
8 | * | ||
9 | * This file is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License, Version 2, as | ||
11 | * published by the Free Software Foundation. | ||
12 | * | ||
13 | * This file is distributed in the hope that it will be useful, but | ||
14 | * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty | ||
15 | * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or | ||
16 | * NONINFRINGEMENT. See the GNU General Public License for more | ||
17 | * details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this file; if not, write to the Free Software | ||
21 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
22 | * or visit http://www.gnu.org/licenses/. | ||
23 | * | ||
24 | * This file may also be available under a different license from Cavium. | ||
25 | * Contact Cavium Networks for more information | ||
26 | ***********************license end**************************************/ | ||
27 | |||
28 | /** | ||
29 | * @file | ||
30 | * | ||
31 | * Support library for the hardware Free Pool Allocator. | ||
32 | * | ||
33 | * | ||
34 | */ | ||
35 | |||
36 | #include "cvmx-config.h" | ||
37 | #include "cvmx.h" | ||
38 | #include "cvmx-fpa.h" | ||
39 | #include "cvmx-ipd.h" | ||
40 | |||
41 | /** | ||
42 | * Current state of all the pools. Use access functions | ||
43 | * instead of using it directly. | ||
44 | */ | ||
45 | CVMX_SHARED cvmx_fpa_pool_info_t cvmx_fpa_pool_info[CVMX_FPA_NUM_POOLS]; | ||
46 | |||
47 | /** | ||
48 | * Setup a FPA pool to control a new block of memory. The | ||
49 | * buffer pointer must be a physical address. | ||
50 | * | ||
51 | * @pool: Pool to initialize | ||
52 | * 0 <= pool < 8 | ||
53 | * @name: Constant character string to name this pool. | ||
54 | * String is not copied. | ||
55 | * @buffer: Pointer to the block of memory to use. This must be | ||
56 | * accessible by all processors and external hardware. | ||
57 | * @block_size: Size for each block controlled by the FPA | ||
58 | * @num_blocks: Number of blocks | ||
59 | * | ||
60 | * Returns 0 on Success, | ||
61 | * -1 on failure | ||
62 | */ | ||
63 | int cvmx_fpa_setup_pool(uint64_t pool, const char *name, void *buffer, | ||
64 | uint64_t block_size, uint64_t num_blocks) | ||
65 | { | ||
66 | char *ptr; | ||
67 | if (!buffer) { | ||
68 | cvmx_dprintf | ||
69 | ("ERROR: cvmx_fpa_setup_pool: NULL buffer pointer!\n"); | ||
70 | return -1; | ||
71 | } | ||
72 | if (pool >= CVMX_FPA_NUM_POOLS) { | ||
73 | cvmx_dprintf("ERROR: cvmx_fpa_setup_pool: Illegal pool!\n"); | ||
74 | return -1; | ||
75 | } | ||
76 | |||
77 | if (block_size < CVMX_FPA_MIN_BLOCK_SIZE) { | ||
78 | cvmx_dprintf | ||
79 | ("ERROR: cvmx_fpa_setup_pool: Block size too small.\n"); | ||
80 | return -1; | ||
81 | } | ||
82 | |||
83 | if (((unsigned long)buffer & (CVMX_FPA_ALIGNMENT - 1)) != 0) { | ||
84 | cvmx_dprintf | ||
85 | ("ERROR: cvmx_fpa_setup_pool: Buffer not aligned properly.\n"); | ||
86 | return -1; | ||
87 | } | ||
88 | |||
89 | cvmx_fpa_pool_info[pool].name = name; | ||
90 | cvmx_fpa_pool_info[pool].size = block_size; | ||
91 | cvmx_fpa_pool_info[pool].starting_element_count = num_blocks; | ||
92 | cvmx_fpa_pool_info[pool].base = buffer; | ||
93 | |||
94 | ptr = (char *)buffer; | ||
95 | while (num_blocks--) { | ||
96 | cvmx_fpa_free(ptr, pool, 0); | ||
97 | ptr += block_size; | ||
98 | } | ||
99 | return 0; | ||
100 | } | ||
101 | |||
102 | /** | ||
103 | * Shutdown a Memory pool and validate that it had all of | ||
104 | * the buffers originally placed in it. | ||
105 | * | ||
106 | * @pool: Pool to shutdown | ||
107 | * Returns Zero on success | ||
108 | * - Positive is count of missing buffers | ||
109 | * - Negative is too many buffers or corrupted pointers | ||
110 | */ | ||
111 | uint64_t cvmx_fpa_shutdown_pool(uint64_t pool) | ||
112 | { | ||
113 | uint64_t errors = 0; | ||
114 | uint64_t count = 0; | ||
115 | uint64_t base = cvmx_ptr_to_phys(cvmx_fpa_pool_info[pool].base); | ||
116 | uint64_t finish = | ||
117 | base + | ||
118 | cvmx_fpa_pool_info[pool].size * | ||
119 | cvmx_fpa_pool_info[pool].starting_element_count; | ||
120 | void *ptr; | ||
121 | uint64_t address; | ||
122 | |||
123 | count = 0; | ||
124 | do { | ||
125 | ptr = cvmx_fpa_alloc(pool); | ||
126 | if (ptr) | ||
127 | address = cvmx_ptr_to_phys(ptr); | ||
128 | else | ||
129 | address = 0; | ||
130 | if (address) { | ||
131 | if ((address >= base) && (address < finish) && | ||
132 | (((address - | ||
133 | base) % cvmx_fpa_pool_info[pool].size) == 0)) { | ||
134 | count++; | ||
135 | } else { | ||
136 | cvmx_dprintf | ||
137 | ("ERROR: cvmx_fpa_shutdown_pool: Illegal address 0x%llx in pool %s(%d)\n", | ||
138 | (unsigned long long)address, | ||
139 | cvmx_fpa_pool_info[pool].name, (int)pool); | ||
140 | errors++; | ||
141 | } | ||
142 | } | ||
143 | } while (address); | ||
144 | |||
145 | #ifdef CVMX_ENABLE_PKO_FUNCTIONS | ||
146 | if (pool == 0) | ||
147 | cvmx_ipd_free_ptr(); | ||
148 | #endif | ||
149 | |||
150 | if (errors) { | ||
151 | cvmx_dprintf | ||
152 | ("ERROR: cvmx_fpa_shutdown_pool: Pool %s(%d) started at 0x%llx, ended at 0x%llx, with a step of 0x%llx\n", | ||
153 | cvmx_fpa_pool_info[pool].name, (int)pool, | ||
154 | (unsigned long long)base, (unsigned long long)finish, | ||
155 | (unsigned long long)cvmx_fpa_pool_info[pool].size); | ||
156 | return -errors; | ||
157 | } else | ||
158 | return 0; | ||
159 | } | ||
160 | |||
161 | uint64_t cvmx_fpa_get_block_size(uint64_t pool) | ||
162 | { | ||
163 | switch (pool) { | ||
164 | case 0: | ||
165 | return CVMX_FPA_POOL_0_SIZE; | ||
166 | case 1: | ||
167 | return CVMX_FPA_POOL_1_SIZE; | ||
168 | case 2: | ||
169 | return CVMX_FPA_POOL_2_SIZE; | ||
170 | case 3: | ||
171 | return CVMX_FPA_POOL_3_SIZE; | ||
172 | case 4: | ||
173 | return CVMX_FPA_POOL_4_SIZE; | ||
174 | case 5: | ||
175 | return CVMX_FPA_POOL_5_SIZE; | ||
176 | case 6: | ||
177 | return CVMX_FPA_POOL_6_SIZE; | ||
178 | case 7: | ||
179 | return CVMX_FPA_POOL_7_SIZE; | ||
180 | default: | ||
181 | return 0; | ||
182 | } | ||
183 | } | ||
diff --git a/arch/mips/cavium-octeon/executive/cvmx-helper-fpa.c b/arch/mips/cavium-octeon/executive/cvmx-helper-fpa.c deleted file mode 100644 index c239e5f4ab9..00000000000 --- a/arch/mips/cavium-octeon/executive/cvmx-helper-fpa.c +++ /dev/null | |||
@@ -1,243 +0,0 @@ | |||
1 | /***********************license start*************** | ||
2 | * Author: Cavium Networks | ||
3 | * | ||
4 | * Contact: support@caviumnetworks.com | ||
5 | * This file is part of the OCTEON SDK | ||
6 | * | ||
7 | * Copyright (c) 2003-2008 Cavium Networks | ||
8 | * | ||
9 | * This file is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License, Version 2, as | ||
11 | * published by the Free Software Foundation. | ||
12 | * | ||
13 | * This file is distributed in the hope that it will be useful, but | ||
14 | * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty | ||
15 | * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or | ||
16 | * NONINFRINGEMENT. See the GNU General Public License for more | ||
17 | * details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this file; if not, write to the Free Software | ||
21 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
22 | * or visit http://www.gnu.org/licenses/. | ||
23 | * | ||
24 | * This file may also be available under a different license from Cavium. | ||
25 | * Contact Cavium Networks for more information | ||
26 | ***********************license end**************************************/ | ||
27 | |||
28 | /** | ||
29 | * @file | ||
30 | * | ||
31 | * Helper functions for FPA setup. | ||
32 | * | ||
33 | */ | ||
34 | #include "executive-config.h" | ||
35 | #include "cvmx-config.h" | ||
36 | #include "cvmx.h" | ||
37 | #include "cvmx-bootmem.h" | ||
38 | #include "cvmx-fpa.h" | ||
39 | #include "cvmx-helper-fpa.h" | ||
40 | |||
41 | /** | ||
42 | * Allocate memory for and initialize a single FPA pool. | ||
43 | * | ||
44 | * @pool: Pool to initialize | ||
45 | * @buffer_size: Size of buffers to allocate in bytes | ||
46 | * @buffers: Number of buffers to put in the pool. Zero is allowed | ||
47 | * @name: String name of the pool for debugging purposes | ||
48 | * Returns Zero on success, non-zero on failure | ||
49 | */ | ||
50 | static int __cvmx_helper_initialize_fpa_pool(int pool, uint64_t buffer_size, | ||
51 | uint64_t buffers, const char *name) | ||
52 | { | ||
53 | uint64_t current_num; | ||
54 | void *memory; | ||
55 | uint64_t align = CVMX_CACHE_LINE_SIZE; | ||
56 | |||
57 | /* | ||
58 | * Align the allocation so that power of 2 size buffers are | ||
59 | * naturally aligned. | ||
60 | */ | ||
61 | while (align < buffer_size) | ||
62 | align = align << 1; | ||
63 | |||
64 | if (buffers == 0) | ||
65 | return 0; | ||
66 | |||
67 | current_num = cvmx_read_csr(CVMX_FPA_QUEX_AVAILABLE(pool)); | ||
68 | if (current_num) { | ||
69 | cvmx_dprintf("Fpa pool %d(%s) already has %llu buffers. " | ||
70 | "Skipping setup.\n", | ||
71 | pool, name, (unsigned long long)current_num); | ||
72 | return 0; | ||
73 | } | ||
74 | |||
75 | memory = cvmx_bootmem_alloc(buffer_size * buffers, align); | ||
76 | if (memory == NULL) { | ||
77 | cvmx_dprintf("Out of memory initializing fpa pool %d(%s).\n", | ||
78 | pool, name); | ||
79 | return -1; | ||
80 | } | ||
81 | cvmx_fpa_setup_pool(pool, name, memory, buffer_size, buffers); | ||
82 | return 0; | ||
83 | } | ||
84 | |||
85 | /** | ||
86 | * Allocate memory and initialize the FPA pools using memory | ||
87 | * from cvmx-bootmem. Specifying zero for the number of | ||
88 | * buffers will cause that FPA pool to not be setup. This is | ||
89 | * useful if you aren't using some of the hardware and want | ||
90 | * to save memory. Use cvmx_helper_initialize_fpa instead of | ||
91 | * this function directly. | ||
92 | * | ||
93 | * @pip_pool: Should always be CVMX_FPA_PACKET_POOL | ||
94 | * @pip_size: Should always be CVMX_FPA_PACKET_POOL_SIZE | ||
95 | * @pip_buffers: | ||
96 | * Number of packet buffers. | ||
97 | * @wqe_pool: Should always be CVMX_FPA_WQE_POOL | ||
98 | * @wqe_size: Should always be CVMX_FPA_WQE_POOL_SIZE | ||
99 | * @wqe_entries: | ||
100 | * Number of work queue entries | ||
101 | * @pko_pool: Should always be CVMX_FPA_OUTPUT_BUFFER_POOL | ||
102 | * @pko_size: Should always be CVMX_FPA_OUTPUT_BUFFER_POOL_SIZE | ||
103 | * @pko_buffers: | ||
104 | * PKO Command buffers. You should at minimum have two per | ||
105 | * each PKO queue. | ||
106 | * @tim_pool: Should always be CVMX_FPA_TIMER_POOL | ||
107 | * @tim_size: Should always be CVMX_FPA_TIMER_POOL_SIZE | ||
108 | * @tim_buffers: | ||
109 | * TIM ring buffer command queues. At least two per timer bucket | ||
110 | * is recommened. | ||
111 | * @dfa_pool: Should always be CVMX_FPA_DFA_POOL | ||
112 | * @dfa_size: Should always be CVMX_FPA_DFA_POOL_SIZE | ||
113 | * @dfa_buffers: | ||
114 | * DFA command buffer. A relatively small (32 for example) | ||
115 | * number should work. | ||
116 | * Returns Zero on success, non-zero if out of memory | ||
117 | */ | ||
118 | static int __cvmx_helper_initialize_fpa(int pip_pool, int pip_size, | ||
119 | int pip_buffers, int wqe_pool, | ||
120 | int wqe_size, int wqe_entries, | ||
121 | int pko_pool, int pko_size, | ||
122 | int pko_buffers, int tim_pool, | ||
123 | int tim_size, int tim_buffers, | ||
124 | int dfa_pool, int dfa_size, | ||
125 | int dfa_buffers) | ||
126 | { | ||
127 | int status; | ||
128 | |||
129 | cvmx_fpa_enable(); | ||
130 | |||
131 | if ((pip_buffers > 0) && (pip_buffers <= 64)) | ||
132 | cvmx_dprintf | ||
133 | ("Warning: %d packet buffers may not be enough for hardware" | ||
134 | " prefetch. 65 or more is recommended.\n", pip_buffers); | ||
135 | |||
136 | if (pip_pool >= 0) { | ||
137 | status = | ||
138 | __cvmx_helper_initialize_fpa_pool(pip_pool, pip_size, | ||
139 | pip_buffers, | ||
140 | "Packet Buffers"); | ||
141 | if (status) | ||
142 | return status; | ||
143 | } | ||
144 | |||
145 | if (wqe_pool >= 0) { | ||
146 | status = | ||
147 | __cvmx_helper_initialize_fpa_pool(wqe_pool, wqe_size, | ||
148 | wqe_entries, | ||
149 | "Work Queue Entries"); | ||
150 | if (status) | ||
151 | return status; | ||
152 | } | ||
153 | |||
154 | if (pko_pool >= 0) { | ||
155 | status = | ||
156 | __cvmx_helper_initialize_fpa_pool(pko_pool, pko_size, | ||
157 | pko_buffers, | ||
158 | "PKO Command Buffers"); | ||
159 | if (status) | ||
160 | return status; | ||
161 | } | ||
162 | |||
163 | if (tim_pool >= 0) { | ||
164 | status = | ||
165 | __cvmx_helper_initialize_fpa_pool(tim_pool, tim_size, | ||
166 | tim_buffers, | ||
167 | "TIM Command Buffers"); | ||
168 | if (status) | ||
169 | return status; | ||
170 | } | ||
171 | |||
172 | if (dfa_pool >= 0) { | ||
173 | status = | ||
174 | __cvmx_helper_initialize_fpa_pool(dfa_pool, dfa_size, | ||
175 | dfa_buffers, | ||
176 | "DFA Command Buffers"); | ||
177 | if (status) | ||
178 | return status; | ||
179 | } | ||
180 | |||
181 | return 0; | ||
182 | } | ||
183 | |||
184 | /** | ||
185 | * Allocate memory and initialize the FPA pools using memory | ||
186 | * from cvmx-bootmem. Sizes of each element in the pools is | ||
187 | * controlled by the cvmx-config.h header file. Specifying | ||
188 | * zero for any parameter will cause that FPA pool to not be | ||
189 | * setup. This is useful if you aren't using some of the | ||
190 | * hardware and want to save memory. | ||
191 | * | ||
192 | * @packet_buffers: | ||
193 | * Number of packet buffers to allocate | ||
194 | * @work_queue_entries: | ||
195 | * Number of work queue entries | ||
196 | * @pko_buffers: | ||
197 | * PKO Command buffers. You should at minimum have two per | ||
198 | * each PKO queue. | ||
199 | * @tim_buffers: | ||
200 | * TIM ring buffer command queues. At least two per timer bucket | ||
201 | * is recommened. | ||
202 | * @dfa_buffers: | ||
203 | * DFA command buffer. A relatively small (32 for example) | ||
204 | * number should work. | ||
205 | * Returns Zero on success, non-zero if out of memory | ||
206 | */ | ||
207 | int cvmx_helper_initialize_fpa(int packet_buffers, int work_queue_entries, | ||
208 | int pko_buffers, int tim_buffers, | ||
209 | int dfa_buffers) | ||
210 | { | ||
211 | #ifndef CVMX_FPA_PACKET_POOL | ||
212 | #define CVMX_FPA_PACKET_POOL -1 | ||
213 | #define CVMX_FPA_PACKET_POOL_SIZE 0 | ||
214 | #endif | ||
215 | #ifndef CVMX_FPA_WQE_POOL | ||
216 | #define CVMX_FPA_WQE_POOL -1 | ||
217 | #define CVMX_FPA_WQE_POOL_SIZE 0 | ||
218 | #endif | ||
219 | #ifndef CVMX_FPA_OUTPUT_BUFFER_POOL | ||
220 | #define CVMX_FPA_OUTPUT_BUFFER_POOL -1 | ||
221 | #define CVMX_FPA_OUTPUT_BUFFER_POOL_SIZE 0 | ||
222 | #endif | ||
223 | #ifndef CVMX_FPA_TIMER_POOL | ||
224 | #define CVMX_FPA_TIMER_POOL -1 | ||
225 | #define CVMX_FPA_TIMER_POOL_SIZE 0 | ||
226 | #endif | ||
227 | #ifndef CVMX_FPA_DFA_POOL | ||
228 | #define CVMX_FPA_DFA_POOL -1 | ||
229 | #define CVMX_FPA_DFA_POOL_SIZE 0 | ||
230 | #endif | ||
231 | return __cvmx_helper_initialize_fpa(CVMX_FPA_PACKET_POOL, | ||
232 | CVMX_FPA_PACKET_POOL_SIZE, | ||
233 | packet_buffers, CVMX_FPA_WQE_POOL, | ||
234 | CVMX_FPA_WQE_POOL_SIZE, | ||
235 | work_queue_entries, | ||
236 | CVMX_FPA_OUTPUT_BUFFER_POOL, | ||
237 | CVMX_FPA_OUTPUT_BUFFER_POOL_SIZE, | ||
238 | pko_buffers, CVMX_FPA_TIMER_POOL, | ||
239 | CVMX_FPA_TIMER_POOL_SIZE, | ||
240 | tim_buffers, CVMX_FPA_DFA_POOL, | ||
241 | CVMX_FPA_DFA_POOL_SIZE, | ||
242 | dfa_buffers); | ||
243 | } | ||
diff --git a/arch/mips/cavium-octeon/octeon-irq.c b/arch/mips/cavium-octeon/octeon-irq.c index ffd4ae660f7..7fb1f222b8a 100644 --- a/arch/mips/cavium-octeon/octeon-irq.c +++ b/arch/mips/cavium-octeon/octeon-irq.c | |||
@@ -3,14 +3,17 @@ | |||
3 | * License. See the file "COPYING" in the main directory of this archive | 3 | * License. See the file "COPYING" in the main directory of this archive |
4 | * for more details. | 4 | * for more details. |
5 | * | 5 | * |
6 | * Copyright (C) 2004-2008, 2009, 2010, 2011 Cavium Networks | 6 | * Copyright (C) 2004-2012 Cavium, Inc. |
7 | */ | 7 | */ |
8 | 8 | ||
9 | #include <linux/interrupt.h> | 9 | #include <linux/interrupt.h> |
10 | #include <linux/irqdomain.h> | ||
10 | #include <linux/bitops.h> | 11 | #include <linux/bitops.h> |
11 | #include <linux/percpu.h> | 12 | #include <linux/percpu.h> |
13 | #include <linux/slab.h> | ||
12 | #include <linux/irq.h> | 14 | #include <linux/irq.h> |
13 | #include <linux/smp.h> | 15 | #include <linux/smp.h> |
16 | #include <linux/of.h> | ||
14 | 17 | ||
15 | #include <asm/octeon/octeon.h> | 18 | #include <asm/octeon/octeon.h> |
16 | 19 | ||
@@ -42,9 +45,9 @@ struct octeon_core_chip_data { | |||
42 | 45 | ||
43 | static struct octeon_core_chip_data octeon_irq_core_chip_data[MIPS_CORE_IRQ_LINES]; | 46 | static struct octeon_core_chip_data octeon_irq_core_chip_data[MIPS_CORE_IRQ_LINES]; |
44 | 47 | ||
45 | static void __init octeon_irq_set_ciu_mapping(int irq, int line, int bit, | 48 | static void octeon_irq_set_ciu_mapping(int irq, int line, int bit, |
46 | struct irq_chip *chip, | 49 | struct irq_chip *chip, |
47 | irq_flow_handler_t handler) | 50 | irq_flow_handler_t handler) |
48 | { | 51 | { |
49 | union octeon_ciu_chip_data cd; | 52 | union octeon_ciu_chip_data cd; |
50 | 53 | ||
@@ -505,6 +508,85 @@ static void octeon_irq_ciu_enable_all_v2(struct irq_data *data) | |||
505 | } | 508 | } |
506 | } | 509 | } |
507 | 510 | ||
511 | static void octeon_irq_gpio_setup(struct irq_data *data) | ||
512 | { | ||
513 | union cvmx_gpio_bit_cfgx cfg; | ||
514 | union octeon_ciu_chip_data cd; | ||
515 | u32 t = irqd_get_trigger_type(data); | ||
516 | |||
517 | cd.p = irq_data_get_irq_chip_data(data); | ||
518 | |||
519 | cfg.u64 = 0; | ||
520 | cfg.s.int_en = 1; | ||
521 | cfg.s.int_type = (t & IRQ_TYPE_EDGE_BOTH) != 0; | ||
522 | cfg.s.rx_xor = (t & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_EDGE_FALLING)) != 0; | ||
523 | |||
524 | /* 140 nS glitch filter*/ | ||
525 | cfg.s.fil_cnt = 7; | ||
526 | cfg.s.fil_sel = 3; | ||
527 | |||
528 | cvmx_write_csr(CVMX_GPIO_BIT_CFGX(cd.s.bit - 16), cfg.u64); | ||
529 | } | ||
530 | |||
531 | static void octeon_irq_ciu_enable_gpio_v2(struct irq_data *data) | ||
532 | { | ||
533 | octeon_irq_gpio_setup(data); | ||
534 | octeon_irq_ciu_enable_v2(data); | ||
535 | } | ||
536 | |||
537 | static void octeon_irq_ciu_enable_gpio(struct irq_data *data) | ||
538 | { | ||
539 | octeon_irq_gpio_setup(data); | ||
540 | octeon_irq_ciu_enable(data); | ||
541 | } | ||
542 | |||
543 | static int octeon_irq_ciu_gpio_set_type(struct irq_data *data, unsigned int t) | ||
544 | { | ||
545 | irqd_set_trigger_type(data, t); | ||
546 | octeon_irq_gpio_setup(data); | ||
547 | |||
548 | return IRQ_SET_MASK_OK; | ||
549 | } | ||
550 | |||
551 | static void octeon_irq_ciu_disable_gpio_v2(struct irq_data *data) | ||
552 | { | ||
553 | union octeon_ciu_chip_data cd; | ||
554 | |||
555 | cd.p = irq_data_get_irq_chip_data(data); | ||
556 | cvmx_write_csr(CVMX_GPIO_BIT_CFGX(cd.s.bit - 16), 0); | ||
557 | |||
558 | octeon_irq_ciu_disable_all_v2(data); | ||
559 | } | ||
560 | |||
561 | static void octeon_irq_ciu_disable_gpio(struct irq_data *data) | ||
562 | { | ||
563 | union octeon_ciu_chip_data cd; | ||
564 | |||
565 | cd.p = irq_data_get_irq_chip_data(data); | ||
566 | cvmx_write_csr(CVMX_GPIO_BIT_CFGX(cd.s.bit - 16), 0); | ||
567 | |||
568 | octeon_irq_ciu_disable_all(data); | ||
569 | } | ||
570 | |||
571 | static void octeon_irq_ciu_gpio_ack(struct irq_data *data) | ||
572 | { | ||
573 | union octeon_ciu_chip_data cd; | ||
574 | u64 mask; | ||
575 | |||
576 | cd.p = irq_data_get_irq_chip_data(data); | ||
577 | mask = 1ull << (cd.s.bit - 16); | ||
578 | |||
579 | cvmx_write_csr(CVMX_GPIO_INT_CLR, mask); | ||
580 | } | ||
581 | |||
582 | static void octeon_irq_handle_gpio(unsigned int irq, struct irq_desc *desc) | ||
583 | { | ||
584 | if (irqd_get_trigger_type(irq_desc_get_irq_data(desc)) & IRQ_TYPE_EDGE_BOTH) | ||
585 | handle_edge_irq(irq, desc); | ||
586 | else | ||
587 | handle_level_irq(irq, desc); | ||
588 | } | ||
589 | |||
508 | #ifdef CONFIG_SMP | 590 | #ifdef CONFIG_SMP |
509 | 591 | ||
510 | static void octeon_irq_cpu_offline_ciu(struct irq_data *data) | 592 | static void octeon_irq_cpu_offline_ciu(struct irq_data *data) |
@@ -650,18 +732,6 @@ static struct irq_chip octeon_irq_chip_ciu_v2 = { | |||
650 | .name = "CIU", | 732 | .name = "CIU", |
651 | .irq_enable = octeon_irq_ciu_enable_v2, | 733 | .irq_enable = octeon_irq_ciu_enable_v2, |
652 | .irq_disable = octeon_irq_ciu_disable_all_v2, | 734 | .irq_disable = octeon_irq_ciu_disable_all_v2, |
653 | .irq_mask = octeon_irq_ciu_disable_local_v2, | ||
654 | .irq_unmask = octeon_irq_ciu_enable_v2, | ||
655 | #ifdef CONFIG_SMP | ||
656 | .irq_set_affinity = octeon_irq_ciu_set_affinity_v2, | ||
657 | .irq_cpu_offline = octeon_irq_cpu_offline_ciu, | ||
658 | #endif | ||
659 | }; | ||
660 | |||
661 | static struct irq_chip octeon_irq_chip_ciu_edge_v2 = { | ||
662 | .name = "CIU-E", | ||
663 | .irq_enable = octeon_irq_ciu_enable_v2, | ||
664 | .irq_disable = octeon_irq_ciu_disable_all_v2, | ||
665 | .irq_ack = octeon_irq_ciu_ack, | 735 | .irq_ack = octeon_irq_ciu_ack, |
666 | .irq_mask = octeon_irq_ciu_disable_local_v2, | 736 | .irq_mask = octeon_irq_ciu_disable_local_v2, |
667 | .irq_unmask = octeon_irq_ciu_enable_v2, | 737 | .irq_unmask = octeon_irq_ciu_enable_v2, |
@@ -675,19 +745,8 @@ static struct irq_chip octeon_irq_chip_ciu = { | |||
675 | .name = "CIU", | 745 | .name = "CIU", |
676 | .irq_enable = octeon_irq_ciu_enable, | 746 | .irq_enable = octeon_irq_ciu_enable, |
677 | .irq_disable = octeon_irq_ciu_disable_all, | 747 | .irq_disable = octeon_irq_ciu_disable_all, |
678 | .irq_mask = octeon_irq_dummy_mask, | ||
679 | #ifdef CONFIG_SMP | ||
680 | .irq_set_affinity = octeon_irq_ciu_set_affinity, | ||
681 | .irq_cpu_offline = octeon_irq_cpu_offline_ciu, | ||
682 | #endif | ||
683 | }; | ||
684 | |||
685 | static struct irq_chip octeon_irq_chip_ciu_edge = { | ||
686 | .name = "CIU-E", | ||
687 | .irq_enable = octeon_irq_ciu_enable, | ||
688 | .irq_disable = octeon_irq_ciu_disable_all, | ||
689 | .irq_mask = octeon_irq_dummy_mask, | ||
690 | .irq_ack = octeon_irq_ciu_ack, | 748 | .irq_ack = octeon_irq_ciu_ack, |
749 | .irq_mask = octeon_irq_dummy_mask, | ||
691 | #ifdef CONFIG_SMP | 750 | #ifdef CONFIG_SMP |
692 | .irq_set_affinity = octeon_irq_ciu_set_affinity, | 751 | .irq_set_affinity = octeon_irq_ciu_set_affinity, |
693 | .irq_cpu_offline = octeon_irq_cpu_offline_ciu, | 752 | .irq_cpu_offline = octeon_irq_cpu_offline_ciu, |
@@ -717,6 +776,33 @@ static struct irq_chip octeon_irq_chip_ciu_mbox = { | |||
717 | .flags = IRQCHIP_ONOFFLINE_ENABLED, | 776 | .flags = IRQCHIP_ONOFFLINE_ENABLED, |
718 | }; | 777 | }; |
719 | 778 | ||
779 | static struct irq_chip octeon_irq_chip_ciu_gpio_v2 = { | ||
780 | .name = "CIU-GPIO", | ||
781 | .irq_enable = octeon_irq_ciu_enable_gpio_v2, | ||
782 | .irq_disable = octeon_irq_ciu_disable_gpio_v2, | ||
783 | .irq_ack = octeon_irq_ciu_gpio_ack, | ||
784 | .irq_mask = octeon_irq_ciu_disable_local_v2, | ||
785 | .irq_unmask = octeon_irq_ciu_enable_v2, | ||
786 | .irq_set_type = octeon_irq_ciu_gpio_set_type, | ||
787 | #ifdef CONFIG_SMP | ||
788 | .irq_set_affinity = octeon_irq_ciu_set_affinity_v2, | ||
789 | #endif | ||
790 | .flags = IRQCHIP_SET_TYPE_MASKED, | ||
791 | }; | ||
792 | |||
793 | static struct irq_chip octeon_irq_chip_ciu_gpio = { | ||
794 | .name = "CIU-GPIO", | ||
795 | .irq_enable = octeon_irq_ciu_enable_gpio, | ||
796 | .irq_disable = octeon_irq_ciu_disable_gpio, | ||
797 | .irq_mask = octeon_irq_dummy_mask, | ||
798 | .irq_ack = octeon_irq_ciu_gpio_ack, | ||
799 | .irq_set_type = octeon_irq_ciu_gpio_set_type, | ||
800 | #ifdef CONFIG_SMP | ||
801 | .irq_set_affinity = octeon_irq_ciu_set_affinity, | ||
802 | #endif | ||
803 | .flags = IRQCHIP_SET_TYPE_MASKED, | ||
804 | }; | ||
805 | |||
720 | /* | 806 | /* |
721 | * Watchdog interrupts are special. They are associated with a single | 807 | * Watchdog interrupts are special. They are associated with a single |
722 | * core, so we hardwire the affinity to that core. | 808 | * core, so we hardwire the affinity to that core. |
@@ -764,6 +850,178 @@ static struct irq_chip octeon_irq_chip_ciu_wd = { | |||
764 | .irq_mask = octeon_irq_dummy_mask, | 850 | .irq_mask = octeon_irq_dummy_mask, |
765 | }; | 851 | }; |
766 | 852 | ||
853 | static bool octeon_irq_ciu_is_edge(unsigned int line, unsigned int bit) | ||
854 | { | ||
855 | bool edge = false; | ||
856 | |||
857 | if (line == 0) | ||
858 | switch (bit) { | ||
859 | case 48 ... 49: /* GMX DRP */ | ||
860 | case 50: /* IPD_DRP */ | ||
861 | case 52 ... 55: /* Timers */ | ||
862 | case 58: /* MPI */ | ||
863 | edge = true; | ||
864 | break; | ||
865 | default: | ||
866 | break; | ||
867 | } | ||
868 | else /* line == 1 */ | ||
869 | switch (bit) { | ||
870 | case 47: /* PTP */ | ||
871 | edge = true; | ||
872 | break; | ||
873 | default: | ||
874 | break; | ||
875 | } | ||
876 | return edge; | ||
877 | } | ||
878 | |||
879 | struct octeon_irq_gpio_domain_data { | ||
880 | unsigned int base_hwirq; | ||
881 | }; | ||
882 | |||
883 | static int octeon_irq_gpio_xlat(struct irq_domain *d, | ||
884 | struct device_node *node, | ||
885 | const u32 *intspec, | ||
886 | unsigned int intsize, | ||
887 | unsigned long *out_hwirq, | ||
888 | unsigned int *out_type) | ||
889 | { | ||
890 | unsigned int type; | ||
891 | unsigned int pin; | ||
892 | unsigned int trigger; | ||
893 | struct octeon_irq_gpio_domain_data *gpiod; | ||
894 | |||
895 | if (d->of_node != node) | ||
896 | return -EINVAL; | ||
897 | |||
898 | if (intsize < 2) | ||
899 | return -EINVAL; | ||
900 | |||
901 | pin = intspec[0]; | ||
902 | if (pin >= 16) | ||
903 | return -EINVAL; | ||
904 | |||
905 | trigger = intspec[1]; | ||
906 | |||
907 | switch (trigger) { | ||
908 | case 1: | ||
909 | type = IRQ_TYPE_EDGE_RISING; | ||
910 | break; | ||
911 | case 2: | ||
912 | type = IRQ_TYPE_EDGE_FALLING; | ||
913 | break; | ||
914 | case 4: | ||
915 | type = IRQ_TYPE_LEVEL_HIGH; | ||
916 | break; | ||
917 | case 8: | ||
918 | type = IRQ_TYPE_LEVEL_LOW; | ||
919 | break; | ||
920 | default: | ||
921 | pr_err("Error: (%s) Invalid irq trigger specification: %x\n", | ||
922 | node->name, | ||
923 | trigger); | ||
924 | type = IRQ_TYPE_LEVEL_LOW; | ||
925 | break; | ||
926 | } | ||
927 | *out_type = type; | ||
928 | gpiod = d->host_data; | ||
929 | *out_hwirq = gpiod->base_hwirq + pin; | ||
930 | |||
931 | return 0; | ||
932 | } | ||
933 | |||
934 | static int octeon_irq_ciu_xlat(struct irq_domain *d, | ||
935 | struct device_node *node, | ||
936 | const u32 *intspec, | ||
937 | unsigned int intsize, | ||
938 | unsigned long *out_hwirq, | ||
939 | unsigned int *out_type) | ||
940 | { | ||
941 | unsigned int ciu, bit; | ||
942 | |||
943 | ciu = intspec[0]; | ||
944 | bit = intspec[1]; | ||
945 | |||
946 | if (ciu > 1 || bit > 63) | ||
947 | return -EINVAL; | ||
948 | |||
949 | /* These are the GPIO lines */ | ||
950 | if (ciu == 0 && bit >= 16 && bit < 32) | ||
951 | return -EINVAL; | ||
952 | |||
953 | *out_hwirq = (ciu << 6) | bit; | ||
954 | *out_type = 0; | ||
955 | |||
956 | return 0; | ||
957 | } | ||
958 | |||
959 | static struct irq_chip *octeon_irq_ciu_chip; | ||
960 | static struct irq_chip *octeon_irq_gpio_chip; | ||
961 | |||
962 | static bool octeon_irq_virq_in_range(unsigned int virq) | ||
963 | { | ||
964 | /* We cannot let it overflow the mapping array. */ | ||
965 | if (virq < (1ul << 8 * sizeof(octeon_irq_ciu_to_irq[0][0]))) | ||
966 | return true; | ||
967 | |||
968 | WARN_ONCE(true, "virq out of range %u.\n", virq); | ||
969 | return false; | ||
970 | } | ||
971 | |||
972 | static int octeon_irq_ciu_map(struct irq_domain *d, | ||
973 | unsigned int virq, irq_hw_number_t hw) | ||
974 | { | ||
975 | unsigned int line = hw >> 6; | ||
976 | unsigned int bit = hw & 63; | ||
977 | |||
978 | if (!octeon_irq_virq_in_range(virq)) | ||
979 | return -EINVAL; | ||
980 | |||
981 | if (line > 1 || octeon_irq_ciu_to_irq[line][bit] != 0) | ||
982 | return -EINVAL; | ||
983 | |||
984 | if (octeon_irq_ciu_is_edge(line, bit)) | ||
985 | octeon_irq_set_ciu_mapping(virq, line, bit, | ||
986 | octeon_irq_ciu_chip, | ||
987 | handle_edge_irq); | ||
988 | else | ||
989 | octeon_irq_set_ciu_mapping(virq, line, bit, | ||
990 | octeon_irq_ciu_chip, | ||
991 | handle_level_irq); | ||
992 | |||
993 | return 0; | ||
994 | } | ||
995 | |||
996 | static int octeon_irq_gpio_map(struct irq_domain *d, | ||
997 | unsigned int virq, irq_hw_number_t hw) | ||
998 | { | ||
999 | unsigned int line = hw >> 6; | ||
1000 | unsigned int bit = hw & 63; | ||
1001 | |||
1002 | if (!octeon_irq_virq_in_range(virq)) | ||
1003 | return -EINVAL; | ||
1004 | |||
1005 | if (line > 1 || octeon_irq_ciu_to_irq[line][bit] != 0) | ||
1006 | return -EINVAL; | ||
1007 | |||
1008 | octeon_irq_set_ciu_mapping(virq, line, bit, | ||
1009 | octeon_irq_gpio_chip, | ||
1010 | octeon_irq_handle_gpio); | ||
1011 | |||
1012 | return 0; | ||
1013 | } | ||
1014 | |||
1015 | static struct irq_domain_ops octeon_irq_domain_ciu_ops = { | ||
1016 | .map = octeon_irq_ciu_map, | ||
1017 | .xlate = octeon_irq_ciu_xlat, | ||
1018 | }; | ||
1019 | |||
1020 | static struct irq_domain_ops octeon_irq_domain_gpio_ops = { | ||
1021 | .map = octeon_irq_gpio_map, | ||
1022 | .xlate = octeon_irq_gpio_xlat, | ||
1023 | }; | ||
1024 | |||
767 | static void octeon_irq_ip2_v1(void) | 1025 | static void octeon_irq_ip2_v1(void) |
768 | { | 1026 | { |
769 | const unsigned long core_id = cvmx_get_core_num(); | 1027 | const unsigned long core_id = cvmx_get_core_num(); |
@@ -887,9 +1145,10 @@ static void __init octeon_irq_init_ciu(void) | |||
887 | { | 1145 | { |
888 | unsigned int i; | 1146 | unsigned int i; |
889 | struct irq_chip *chip; | 1147 | struct irq_chip *chip; |
890 | struct irq_chip *chip_edge; | ||
891 | struct irq_chip *chip_mbox; | 1148 | struct irq_chip *chip_mbox; |
892 | struct irq_chip *chip_wd; | 1149 | struct irq_chip *chip_wd; |
1150 | struct device_node *gpio_node; | ||
1151 | struct device_node *ciu_node; | ||
893 | 1152 | ||
894 | octeon_irq_init_ciu_percpu(); | 1153 | octeon_irq_init_ciu_percpu(); |
895 | octeon_irq_setup_secondary = octeon_irq_setup_secondary_ciu; | 1154 | octeon_irq_setup_secondary = octeon_irq_setup_secondary_ciu; |
@@ -901,17 +1160,18 @@ static void __init octeon_irq_init_ciu(void) | |||
901 | octeon_irq_ip2 = octeon_irq_ip2_v2; | 1160 | octeon_irq_ip2 = octeon_irq_ip2_v2; |
902 | octeon_irq_ip3 = octeon_irq_ip3_v2; | 1161 | octeon_irq_ip3 = octeon_irq_ip3_v2; |
903 | chip = &octeon_irq_chip_ciu_v2; | 1162 | chip = &octeon_irq_chip_ciu_v2; |
904 | chip_edge = &octeon_irq_chip_ciu_edge_v2; | ||
905 | chip_mbox = &octeon_irq_chip_ciu_mbox_v2; | 1163 | chip_mbox = &octeon_irq_chip_ciu_mbox_v2; |
906 | chip_wd = &octeon_irq_chip_ciu_wd_v2; | 1164 | chip_wd = &octeon_irq_chip_ciu_wd_v2; |
1165 | octeon_irq_gpio_chip = &octeon_irq_chip_ciu_gpio_v2; | ||
907 | } else { | 1166 | } else { |
908 | octeon_irq_ip2 = octeon_irq_ip2_v1; | 1167 | octeon_irq_ip2 = octeon_irq_ip2_v1; |
909 | octeon_irq_ip3 = octeon_irq_ip3_v1; | 1168 | octeon_irq_ip3 = octeon_irq_ip3_v1; |
910 | chip = &octeon_irq_chip_ciu; | 1169 | chip = &octeon_irq_chip_ciu; |
911 | chip_edge = &octeon_irq_chip_ciu_edge; | ||
912 | chip_mbox = &octeon_irq_chip_ciu_mbox; | 1170 | chip_mbox = &octeon_irq_chip_ciu_mbox; |
913 | chip_wd = &octeon_irq_chip_ciu_wd; | 1171 | chip_wd = &octeon_irq_chip_ciu_wd; |
1172 | octeon_irq_gpio_chip = &octeon_irq_chip_ciu_gpio; | ||
914 | } | 1173 | } |
1174 | octeon_irq_ciu_chip = chip; | ||
915 | octeon_irq_ip4 = octeon_irq_ip4_mask; | 1175 | octeon_irq_ip4 = octeon_irq_ip4_mask; |
916 | 1176 | ||
917 | /* Mips internal */ | 1177 | /* Mips internal */ |
@@ -920,80 +1180,49 @@ static void __init octeon_irq_init_ciu(void) | |||
920 | /* CIU_0 */ | 1180 | /* CIU_0 */ |
921 | for (i = 0; i < 16; i++) | 1181 | for (i = 0; i < 16; i++) |
922 | octeon_irq_set_ciu_mapping(i + OCTEON_IRQ_WORKQ0, 0, i + 0, chip, handle_level_irq); | 1182 | octeon_irq_set_ciu_mapping(i + OCTEON_IRQ_WORKQ0, 0, i + 0, chip, handle_level_irq); |
923 | for (i = 0; i < 16; i++) | ||
924 | octeon_irq_set_ciu_mapping(i + OCTEON_IRQ_GPIO0, 0, i + 16, chip, handle_level_irq); | ||
925 | 1183 | ||
926 | octeon_irq_set_ciu_mapping(OCTEON_IRQ_MBOX0, 0, 32, chip_mbox, handle_percpu_irq); | 1184 | octeon_irq_set_ciu_mapping(OCTEON_IRQ_MBOX0, 0, 32, chip_mbox, handle_percpu_irq); |
927 | octeon_irq_set_ciu_mapping(OCTEON_IRQ_MBOX1, 0, 33, chip_mbox, handle_percpu_irq); | 1185 | octeon_irq_set_ciu_mapping(OCTEON_IRQ_MBOX1, 0, 33, chip_mbox, handle_percpu_irq); |
928 | 1186 | ||
929 | octeon_irq_set_ciu_mapping(OCTEON_IRQ_UART0, 0, 34, chip, handle_level_irq); | ||
930 | octeon_irq_set_ciu_mapping(OCTEON_IRQ_UART1, 0, 35, chip, handle_level_irq); | ||
931 | |||
932 | for (i = 0; i < 4; i++) | 1187 | for (i = 0; i < 4; i++) |
933 | octeon_irq_set_ciu_mapping(i + OCTEON_IRQ_PCI_INT0, 0, i + 36, chip, handle_level_irq); | 1188 | octeon_irq_set_ciu_mapping(i + OCTEON_IRQ_PCI_INT0, 0, i + 36, chip, handle_level_irq); |
934 | for (i = 0; i < 4; i++) | 1189 | for (i = 0; i < 4; i++) |
935 | octeon_irq_set_ciu_mapping(i + OCTEON_IRQ_PCI_MSI0, 0, i + 40, chip, handle_level_irq); | 1190 | octeon_irq_set_ciu_mapping(i + OCTEON_IRQ_PCI_MSI0, 0, i + 40, chip, handle_level_irq); |
936 | 1191 | ||
937 | octeon_irq_set_ciu_mapping(OCTEON_IRQ_TWSI, 0, 45, chip, handle_level_irq); | ||
938 | octeon_irq_set_ciu_mapping(OCTEON_IRQ_RML, 0, 46, chip, handle_level_irq); | 1192 | octeon_irq_set_ciu_mapping(OCTEON_IRQ_RML, 0, 46, chip, handle_level_irq); |
939 | octeon_irq_set_ciu_mapping(OCTEON_IRQ_TRACE0, 0, 47, chip, handle_level_irq); | ||
940 | |||
941 | for (i = 0; i < 2; i++) | ||
942 | octeon_irq_set_ciu_mapping(i + OCTEON_IRQ_GMX_DRP0, 0, i + 48, chip_edge, handle_edge_irq); | ||
943 | |||
944 | octeon_irq_set_ciu_mapping(OCTEON_IRQ_IPD_DRP, 0, 50, chip_edge, handle_edge_irq); | ||
945 | octeon_irq_set_ciu_mapping(OCTEON_IRQ_KEY_ZERO, 0, 51, chip_edge, handle_edge_irq); | ||
946 | |||
947 | for (i = 0; i < 4; i++) | 1193 | for (i = 0; i < 4; i++) |
948 | octeon_irq_set_ciu_mapping(i + OCTEON_IRQ_TIMER0, 0, i + 52, chip_edge, handle_edge_irq); | 1194 | octeon_irq_set_ciu_mapping(i + OCTEON_IRQ_TIMER0, 0, i + 52, chip, handle_edge_irq); |
949 | 1195 | ||
950 | octeon_irq_set_ciu_mapping(OCTEON_IRQ_USB0, 0, 56, chip, handle_level_irq); | 1196 | octeon_irq_set_ciu_mapping(OCTEON_IRQ_USB0, 0, 56, chip, handle_level_irq); |
951 | octeon_irq_set_ciu_mapping(OCTEON_IRQ_PCM, 0, 57, chip, handle_level_irq); | ||
952 | octeon_irq_set_ciu_mapping(OCTEON_IRQ_MPI, 0, 58, chip, handle_level_irq); | ||
953 | octeon_irq_set_ciu_mapping(OCTEON_IRQ_TWSI2, 0, 59, chip, handle_level_irq); | ||
954 | octeon_irq_set_ciu_mapping(OCTEON_IRQ_POWIQ, 0, 60, chip, handle_level_irq); | ||
955 | octeon_irq_set_ciu_mapping(OCTEON_IRQ_IPDPPTHR, 0, 61, chip, handle_level_irq); | ||
956 | octeon_irq_set_ciu_mapping(OCTEON_IRQ_MII0, 0, 62, chip, handle_level_irq); | ||
957 | octeon_irq_set_ciu_mapping(OCTEON_IRQ_BOOTDMA, 0, 63, chip, handle_level_irq); | 1197 | octeon_irq_set_ciu_mapping(OCTEON_IRQ_BOOTDMA, 0, 63, chip, handle_level_irq); |
958 | 1198 | ||
959 | /* CIU_1 */ | 1199 | /* CIU_1 */ |
960 | for (i = 0; i < 16; i++) | 1200 | for (i = 0; i < 16; i++) |
961 | octeon_irq_set_ciu_mapping(i + OCTEON_IRQ_WDOG0, 1, i + 0, chip_wd, handle_level_irq); | 1201 | octeon_irq_set_ciu_mapping(i + OCTEON_IRQ_WDOG0, 1, i + 0, chip_wd, handle_level_irq); |
962 | 1202 | ||
963 | octeon_irq_set_ciu_mapping(OCTEON_IRQ_UART2, 1, 16, chip, handle_level_irq); | ||
964 | octeon_irq_set_ciu_mapping(OCTEON_IRQ_USB1, 1, 17, chip, handle_level_irq); | 1203 | octeon_irq_set_ciu_mapping(OCTEON_IRQ_USB1, 1, 17, chip, handle_level_irq); |
965 | octeon_irq_set_ciu_mapping(OCTEON_IRQ_MII1, 1, 18, chip, handle_level_irq); | 1204 | |
966 | octeon_irq_set_ciu_mapping(OCTEON_IRQ_NAND, 1, 19, chip, handle_level_irq); | 1205 | gpio_node = of_find_compatible_node(NULL, NULL, "cavium,octeon-3860-gpio"); |
967 | octeon_irq_set_ciu_mapping(OCTEON_IRQ_MIO, 1, 20, chip, handle_level_irq); | 1206 | if (gpio_node) { |
968 | octeon_irq_set_ciu_mapping(OCTEON_IRQ_IOB, 1, 21, chip, handle_level_irq); | 1207 | struct octeon_irq_gpio_domain_data *gpiod; |
969 | octeon_irq_set_ciu_mapping(OCTEON_IRQ_FPA, 1, 22, chip, handle_level_irq); | 1208 | |
970 | octeon_irq_set_ciu_mapping(OCTEON_IRQ_POW, 1, 23, chip, handle_level_irq); | 1209 | gpiod = kzalloc(sizeof(*gpiod), GFP_KERNEL); |
971 | octeon_irq_set_ciu_mapping(OCTEON_IRQ_L2C, 1, 24, chip, handle_level_irq); | 1210 | if (gpiod) { |
972 | octeon_irq_set_ciu_mapping(OCTEON_IRQ_IPD, 1, 25, chip, handle_level_irq); | 1211 | /* gpio domain host_data is the base hwirq number. */ |
973 | octeon_irq_set_ciu_mapping(OCTEON_IRQ_PIP, 1, 26, chip, handle_level_irq); | 1212 | gpiod->base_hwirq = 16; |
974 | octeon_irq_set_ciu_mapping(OCTEON_IRQ_PKO, 1, 27, chip, handle_level_irq); | 1213 | irq_domain_add_linear(gpio_node, 16, &octeon_irq_domain_gpio_ops, gpiod); |
975 | octeon_irq_set_ciu_mapping(OCTEON_IRQ_ZIP, 1, 28, chip, handle_level_irq); | 1214 | of_node_put(gpio_node); |
976 | octeon_irq_set_ciu_mapping(OCTEON_IRQ_TIM, 1, 29, chip, handle_level_irq); | 1215 | } else |
977 | octeon_irq_set_ciu_mapping(OCTEON_IRQ_RAD, 1, 30, chip, handle_level_irq); | 1216 | pr_warn("Cannot allocate memory for GPIO irq_domain.\n"); |
978 | octeon_irq_set_ciu_mapping(OCTEON_IRQ_KEY, 1, 31, chip, handle_level_irq); | 1217 | } else |
979 | octeon_irq_set_ciu_mapping(OCTEON_IRQ_DFA, 1, 32, chip, handle_level_irq); | 1218 | pr_warn("Cannot find device node for cavium,octeon-3860-gpio.\n"); |
980 | octeon_irq_set_ciu_mapping(OCTEON_IRQ_USBCTL, 1, 33, chip, handle_level_irq); | 1219 | |
981 | octeon_irq_set_ciu_mapping(OCTEON_IRQ_SLI, 1, 34, chip, handle_level_irq); | 1220 | ciu_node = of_find_compatible_node(NULL, NULL, "cavium,octeon-3860-ciu"); |
982 | octeon_irq_set_ciu_mapping(OCTEON_IRQ_DPI, 1, 35, chip, handle_level_irq); | 1221 | if (ciu_node) { |
983 | 1222 | irq_domain_add_tree(ciu_node, &octeon_irq_domain_ciu_ops, NULL); | |
984 | octeon_irq_set_ciu_mapping(OCTEON_IRQ_AGX0, 1, 36, chip, handle_level_irq); | 1223 | of_node_put(ciu_node); |
985 | 1224 | } else | |
986 | octeon_irq_set_ciu_mapping(OCTEON_IRQ_AGL, 1, 46, chip, handle_level_irq); | 1225 | pr_warn("Cannot find device node for cavium,octeon-3860-ciu.\n"); |
987 | |||
988 | octeon_irq_set_ciu_mapping(OCTEON_IRQ_PTP, 1, 47, chip_edge, handle_edge_irq); | ||
989 | |||
990 | octeon_irq_set_ciu_mapping(OCTEON_IRQ_PEM0, 1, 48, chip, handle_level_irq); | ||
991 | octeon_irq_set_ciu_mapping(OCTEON_IRQ_PEM1, 1, 49, chip, handle_level_irq); | ||
992 | octeon_irq_set_ciu_mapping(OCTEON_IRQ_SRIO0, 1, 50, chip, handle_level_irq); | ||
993 | octeon_irq_set_ciu_mapping(OCTEON_IRQ_SRIO1, 1, 51, chip, handle_level_irq); | ||
994 | octeon_irq_set_ciu_mapping(OCTEON_IRQ_LMC0, 1, 52, chip, handle_level_irq); | ||
995 | octeon_irq_set_ciu_mapping(OCTEON_IRQ_DFM, 1, 56, chip, handle_level_irq); | ||
996 | octeon_irq_set_ciu_mapping(OCTEON_IRQ_RST, 1, 63, chip, handle_level_irq); | ||
997 | 1226 | ||
998 | /* Enable the CIU lines */ | 1227 | /* Enable the CIU lines */ |
999 | set_c0_status(STATUSF_IP3 | STATUSF_IP2); | 1228 | set_c0_status(STATUSF_IP3 | STATUSF_IP2); |
diff --git a/arch/mips/cavium-octeon/octeon-memcpy.S b/arch/mips/cavium-octeon/octeon-memcpy.S index 88e0cddca20..db478dbb9c7 100644 --- a/arch/mips/cavium-octeon/octeon-memcpy.S +++ b/arch/mips/cavium-octeon/octeon-memcpy.S | |||
@@ -164,6 +164,14 @@ | |||
164 | .set noat | 164 | .set noat |
165 | 165 | ||
166 | /* | 166 | /* |
167 | * t7 is used as a flag to note inatomic mode. | ||
168 | */ | ||
169 | LEAF(__copy_user_inatomic) | ||
170 | b __copy_user_common | ||
171 | li t7, 1 | ||
172 | END(__copy_user_inatomic) | ||
173 | |||
174 | /* | ||
167 | * A combined memcpy/__copy_user | 175 | * A combined memcpy/__copy_user |
168 | * __copy_user sets len to 0 for success; else to an upper bound of | 176 | * __copy_user sets len to 0 for success; else to an upper bound of |
169 | * the number of uncopied bytes. | 177 | * the number of uncopied bytes. |
@@ -174,6 +182,8 @@ LEAF(memcpy) /* a0=dst a1=src a2=len */ | |||
174 | move v0, dst /* return value */ | 182 | move v0, dst /* return value */ |
175 | __memcpy: | 183 | __memcpy: |
176 | FEXPORT(__copy_user) | 184 | FEXPORT(__copy_user) |
185 | li t7, 0 /* not inatomic */ | ||
186 | __copy_user_common: | ||
177 | /* | 187 | /* |
178 | * Note: dst & src may be unaligned, len may be 0 | 188 | * Note: dst & src may be unaligned, len may be 0 |
179 | * Temps | 189 | * Temps |
@@ -412,7 +422,6 @@ l_exc_copy: | |||
412 | * Assumes src < THREAD_BUADDR($28) | 422 | * Assumes src < THREAD_BUADDR($28) |
413 | */ | 423 | */ |
414 | LOAD t0, TI_TASK($28) | 424 | LOAD t0, TI_TASK($28) |
415 | nop | ||
416 | LOAD t0, THREAD_BUADDR(t0) | 425 | LOAD t0, THREAD_BUADDR(t0) |
417 | 1: | 426 | 1: |
418 | EXC( lb t1, 0(src), l_exc) | 427 | EXC( lb t1, 0(src), l_exc) |
@@ -422,10 +431,9 @@ EXC( lb t1, 0(src), l_exc) | |||
422 | ADD dst, dst, 1 | 431 | ADD dst, dst, 1 |
423 | l_exc: | 432 | l_exc: |
424 | LOAD t0, TI_TASK($28) | 433 | LOAD t0, TI_TASK($28) |
425 | nop | ||
426 | LOAD t0, THREAD_BUADDR(t0) # t0 is just past last good address | 434 | LOAD t0, THREAD_BUADDR(t0) # t0 is just past last good address |
427 | nop | ||
428 | SUB len, AT, t0 # len number of uncopied bytes | 435 | SUB len, AT, t0 # len number of uncopied bytes |
436 | bnez t7, 2f /* Skip the zeroing out part if inatomic */ | ||
429 | /* | 437 | /* |
430 | * Here's where we rely on src and dst being incremented in tandem, | 438 | * Here's where we rely on src and dst being incremented in tandem, |
431 | * See (3) above. | 439 | * See (3) above. |
@@ -443,7 +451,7 @@ l_exc: | |||
443 | ADD dst, dst, 1 | 451 | ADD dst, dst, 1 |
444 | bnez src, 1b | 452 | bnez src, 1b |
445 | SUB src, src, 1 | 453 | SUB src, src, 1 |
446 | jr ra | 454 | 2: jr ra |
447 | nop | 455 | nop |
448 | 456 | ||
449 | 457 | ||
diff --git a/arch/mips/cavium-octeon/octeon-platform.c b/arch/mips/cavium-octeon/octeon-platform.c index cd61d7281d9..0938df10a71 100644 --- a/arch/mips/cavium-octeon/octeon-platform.c +++ b/arch/mips/cavium-octeon/octeon-platform.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * License. See the file "COPYING" in the main directory of this archive | 3 | * License. See the file "COPYING" in the main directory of this archive |
4 | * for more details. | 4 | * for more details. |
5 | * | 5 | * |
6 | * Copyright (C) 2004-2010 Cavium Networks | 6 | * Copyright (C) 2004-2011 Cavium Networks |
7 | * Copyright (C) 2008 Wind River Systems | 7 | * Copyright (C) 2008 Wind River Systems |
8 | */ | 8 | */ |
9 | 9 | ||
@@ -13,10 +13,16 @@ | |||
13 | #include <linux/usb.h> | 13 | #include <linux/usb.h> |
14 | #include <linux/dma-mapping.h> | 14 | #include <linux/dma-mapping.h> |
15 | #include <linux/module.h> | 15 | #include <linux/module.h> |
16 | #include <linux/slab.h> | ||
16 | #include <linux/platform_device.h> | 17 | #include <linux/platform_device.h> |
18 | #include <linux/of_platform.h> | ||
19 | #include <linux/of_fdt.h> | ||
20 | #include <linux/libfdt.h> | ||
17 | 21 | ||
18 | #include <asm/octeon/octeon.h> | 22 | #include <asm/octeon/octeon.h> |
19 | #include <asm/octeon/cvmx-rnm-defs.h> | 23 | #include <asm/octeon/cvmx-rnm-defs.h> |
24 | #include <asm/octeon/cvmx-helper.h> | ||
25 | #include <asm/octeon/cvmx-helper-board.h> | ||
20 | 26 | ||
21 | static struct octeon_cf_data octeon_cf_data; | 27 | static struct octeon_cf_data octeon_cf_data; |
22 | 28 | ||
@@ -162,182 +168,6 @@ out: | |||
162 | } | 168 | } |
163 | device_initcall(octeon_rng_device_init); | 169 | device_initcall(octeon_rng_device_init); |
164 | 170 | ||
165 | static struct i2c_board_info __initdata octeon_i2c_devices[] = { | ||
166 | { | ||
167 | I2C_BOARD_INFO("ds1337", 0x68), | ||
168 | }, | ||
169 | }; | ||
170 | |||
171 | static int __init octeon_i2c_devices_init(void) | ||
172 | { | ||
173 | return i2c_register_board_info(0, octeon_i2c_devices, | ||
174 | ARRAY_SIZE(octeon_i2c_devices)); | ||
175 | } | ||
176 | arch_initcall(octeon_i2c_devices_init); | ||
177 | |||
178 | #define OCTEON_I2C_IO_BASE 0x1180000001000ull | ||
179 | #define OCTEON_I2C_IO_UNIT_OFFSET 0x200 | ||
180 | |||
181 | static struct octeon_i2c_data octeon_i2c_data[2]; | ||
182 | |||
183 | static int __init octeon_i2c_device_init(void) | ||
184 | { | ||
185 | struct platform_device *pd; | ||
186 | int ret = 0; | ||
187 | int port, num_ports; | ||
188 | |||
189 | struct resource i2c_resources[] = { | ||
190 | { | ||
191 | .flags = IORESOURCE_MEM, | ||
192 | }, { | ||
193 | .flags = IORESOURCE_IRQ, | ||
194 | } | ||
195 | }; | ||
196 | |||
197 | if (OCTEON_IS_MODEL(OCTEON_CN56XX) || OCTEON_IS_MODEL(OCTEON_CN52XX)) | ||
198 | num_ports = 2; | ||
199 | else | ||
200 | num_ports = 1; | ||
201 | |||
202 | for (port = 0; port < num_ports; port++) { | ||
203 | octeon_i2c_data[port].sys_freq = octeon_get_io_clock_rate(); | ||
204 | /*FIXME: should be examined. At the moment is set for 100Khz */ | ||
205 | octeon_i2c_data[port].i2c_freq = 100000; | ||
206 | |||
207 | pd = platform_device_alloc("i2c-octeon", port); | ||
208 | if (!pd) { | ||
209 | ret = -ENOMEM; | ||
210 | goto out; | ||
211 | } | ||
212 | |||
213 | pd->dev.platform_data = octeon_i2c_data + port; | ||
214 | |||
215 | i2c_resources[0].start = | ||
216 | OCTEON_I2C_IO_BASE + (port * OCTEON_I2C_IO_UNIT_OFFSET); | ||
217 | i2c_resources[0].end = i2c_resources[0].start + 0x1f; | ||
218 | switch (port) { | ||
219 | case 0: | ||
220 | i2c_resources[1].start = OCTEON_IRQ_TWSI; | ||
221 | i2c_resources[1].end = OCTEON_IRQ_TWSI; | ||
222 | break; | ||
223 | case 1: | ||
224 | i2c_resources[1].start = OCTEON_IRQ_TWSI2; | ||
225 | i2c_resources[1].end = OCTEON_IRQ_TWSI2; | ||
226 | break; | ||
227 | default: | ||
228 | BUG(); | ||
229 | } | ||
230 | |||
231 | ret = platform_device_add_resources(pd, | ||
232 | i2c_resources, | ||
233 | ARRAY_SIZE(i2c_resources)); | ||
234 | if (ret) | ||
235 | goto fail; | ||
236 | |||
237 | ret = platform_device_add(pd); | ||
238 | if (ret) | ||
239 | goto fail; | ||
240 | } | ||
241 | return ret; | ||
242 | fail: | ||
243 | platform_device_put(pd); | ||
244 | out: | ||
245 | return ret; | ||
246 | } | ||
247 | device_initcall(octeon_i2c_device_init); | ||
248 | |||
249 | /* Octeon SMI/MDIO interface. */ | ||
250 | static int __init octeon_mdiobus_device_init(void) | ||
251 | { | ||
252 | struct platform_device *pd; | ||
253 | int ret = 0; | ||
254 | |||
255 | if (octeon_is_simulation()) | ||
256 | return 0; /* No mdio in the simulator. */ | ||
257 | |||
258 | /* The bus number is the platform_device id. */ | ||
259 | pd = platform_device_alloc("mdio-octeon", 0); | ||
260 | if (!pd) { | ||
261 | ret = -ENOMEM; | ||
262 | goto out; | ||
263 | } | ||
264 | |||
265 | ret = platform_device_add(pd); | ||
266 | if (ret) | ||
267 | goto fail; | ||
268 | |||
269 | return ret; | ||
270 | fail: | ||
271 | platform_device_put(pd); | ||
272 | |||
273 | out: | ||
274 | return ret; | ||
275 | |||
276 | } | ||
277 | device_initcall(octeon_mdiobus_device_init); | ||
278 | |||
279 | /* Octeon mgmt port Ethernet interface. */ | ||
280 | static int __init octeon_mgmt_device_init(void) | ||
281 | { | ||
282 | struct platform_device *pd; | ||
283 | int ret = 0; | ||
284 | int port, num_ports; | ||
285 | |||
286 | struct resource mgmt_port_resource = { | ||
287 | .flags = IORESOURCE_IRQ, | ||
288 | .start = -1, | ||
289 | .end = -1 | ||
290 | }; | ||
291 | |||
292 | if (!OCTEON_IS_MODEL(OCTEON_CN56XX) && !OCTEON_IS_MODEL(OCTEON_CN52XX)) | ||
293 | return 0; | ||
294 | |||
295 | if (OCTEON_IS_MODEL(OCTEON_CN56XX)) | ||
296 | num_ports = 1; | ||
297 | else | ||
298 | num_ports = 2; | ||
299 | |||
300 | for (port = 0; port < num_ports; port++) { | ||
301 | pd = platform_device_alloc("octeon_mgmt", port); | ||
302 | if (!pd) { | ||
303 | ret = -ENOMEM; | ||
304 | goto out; | ||
305 | } | ||
306 | /* No DMA restrictions */ | ||
307 | pd->dev.coherent_dma_mask = DMA_BIT_MASK(64); | ||
308 | pd->dev.dma_mask = &pd->dev.coherent_dma_mask; | ||
309 | |||
310 | switch (port) { | ||
311 | case 0: | ||
312 | mgmt_port_resource.start = OCTEON_IRQ_MII0; | ||
313 | break; | ||
314 | case 1: | ||
315 | mgmt_port_resource.start = OCTEON_IRQ_MII1; | ||
316 | break; | ||
317 | default: | ||
318 | BUG(); | ||
319 | } | ||
320 | mgmt_port_resource.end = mgmt_port_resource.start; | ||
321 | |||
322 | ret = platform_device_add_resources(pd, &mgmt_port_resource, 1); | ||
323 | |||
324 | if (ret) | ||
325 | goto fail; | ||
326 | |||
327 | ret = platform_device_add(pd); | ||
328 | if (ret) | ||
329 | goto fail; | ||
330 | } | ||
331 | return ret; | ||
332 | fail: | ||
333 | platform_device_put(pd); | ||
334 | |||
335 | out: | ||
336 | return ret; | ||
337 | |||
338 | } | ||
339 | device_initcall(octeon_mgmt_device_init); | ||
340 | |||
341 | #ifdef CONFIG_USB | 171 | #ifdef CONFIG_USB |
342 | 172 | ||
343 | static int __init octeon_ehci_device_init(void) | 173 | static int __init octeon_ehci_device_init(void) |
@@ -440,6 +270,521 @@ device_initcall(octeon_ohci_device_init); | |||
440 | 270 | ||
441 | #endif /* CONFIG_USB */ | 271 | #endif /* CONFIG_USB */ |
442 | 272 | ||
273 | static struct of_device_id __initdata octeon_ids[] = { | ||
274 | { .compatible = "simple-bus", }, | ||
275 | { .compatible = "cavium,octeon-6335-uctl", }, | ||
276 | { .compatible = "cavium,octeon-3860-bootbus", }, | ||
277 | { .compatible = "cavium,mdio-mux", }, | ||
278 | { .compatible = "gpio-leds", }, | ||
279 | {}, | ||
280 | }; | ||
281 | |||
282 | static bool __init octeon_has_88e1145(void) | ||
283 | { | ||
284 | return !OCTEON_IS_MODEL(OCTEON_CN52XX) && | ||
285 | !OCTEON_IS_MODEL(OCTEON_CN6XXX) && | ||
286 | !OCTEON_IS_MODEL(OCTEON_CN56XX); | ||
287 | } | ||
288 | |||
289 | static void __init octeon_fdt_set_phy(int eth, int phy_addr) | ||
290 | { | ||
291 | const __be32 *phy_handle; | ||
292 | const __be32 *alt_phy_handle; | ||
293 | const __be32 *reg; | ||
294 | u32 phandle; | ||
295 | int phy; | ||
296 | int alt_phy; | ||
297 | const char *p; | ||
298 | int current_len; | ||
299 | char new_name[20]; | ||
300 | |||
301 | phy_handle = fdt_getprop(initial_boot_params, eth, "phy-handle", NULL); | ||
302 | if (!phy_handle) | ||
303 | return; | ||
304 | |||
305 | phandle = be32_to_cpup(phy_handle); | ||
306 | phy = fdt_node_offset_by_phandle(initial_boot_params, phandle); | ||
307 | |||
308 | alt_phy_handle = fdt_getprop(initial_boot_params, eth, "cavium,alt-phy-handle", NULL); | ||
309 | if (alt_phy_handle) { | ||
310 | u32 alt_phandle = be32_to_cpup(alt_phy_handle); | ||
311 | alt_phy = fdt_node_offset_by_phandle(initial_boot_params, alt_phandle); | ||
312 | } else { | ||
313 | alt_phy = -1; | ||
314 | } | ||
315 | |||
316 | if (phy_addr < 0 || phy < 0) { | ||
317 | /* Delete the PHY things */ | ||
318 | fdt_nop_property(initial_boot_params, eth, "phy-handle"); | ||
319 | /* This one may fail */ | ||
320 | fdt_nop_property(initial_boot_params, eth, "cavium,alt-phy-handle"); | ||
321 | if (phy >= 0) | ||
322 | fdt_nop_node(initial_boot_params, phy); | ||
323 | if (alt_phy >= 0) | ||
324 | fdt_nop_node(initial_boot_params, alt_phy); | ||
325 | return; | ||
326 | } | ||
327 | |||
328 | if (phy_addr >= 256 && alt_phy > 0) { | ||
329 | const struct fdt_property *phy_prop; | ||
330 | struct fdt_property *alt_prop; | ||
331 | u32 phy_handle_name; | ||
332 | |||
333 | /* Use the alt phy node instead.*/ | ||
334 | phy_prop = fdt_get_property(initial_boot_params, eth, "phy-handle", NULL); | ||
335 | phy_handle_name = phy_prop->nameoff; | ||
336 | fdt_nop_node(initial_boot_params, phy); | ||
337 | fdt_nop_property(initial_boot_params, eth, "phy-handle"); | ||
338 | alt_prop = fdt_get_property_w(initial_boot_params, eth, "cavium,alt-phy-handle", NULL); | ||
339 | alt_prop->nameoff = phy_handle_name; | ||
340 | phy = alt_phy; | ||
341 | } | ||
342 | |||
343 | phy_addr &= 0xff; | ||
344 | |||
345 | if (octeon_has_88e1145()) { | ||
346 | fdt_nop_property(initial_boot_params, phy, "marvell,reg-init"); | ||
347 | memset(new_name, 0, sizeof(new_name)); | ||
348 | strcpy(new_name, "marvell,88e1145"); | ||
349 | p = fdt_getprop(initial_boot_params, phy, "compatible", | ||
350 | ¤t_len); | ||
351 | if (p && current_len >= strlen(new_name)) | ||
352 | fdt_setprop_inplace(initial_boot_params, phy, | ||
353 | "compatible", new_name, current_len); | ||
354 | } | ||
355 | |||
356 | reg = fdt_getprop(initial_boot_params, phy, "reg", NULL); | ||
357 | if (phy_addr == be32_to_cpup(reg)) | ||
358 | return; | ||
359 | |||
360 | fdt_setprop_inplace_cell(initial_boot_params, phy, "reg", phy_addr); | ||
361 | |||
362 | snprintf(new_name, sizeof(new_name), "ethernet-phy@%x", phy_addr); | ||
363 | |||
364 | p = fdt_get_name(initial_boot_params, phy, ¤t_len); | ||
365 | if (p && current_len == strlen(new_name)) | ||
366 | fdt_set_name(initial_boot_params, phy, new_name); | ||
367 | else | ||
368 | pr_err("Error: could not rename ethernet phy: <%s>", p); | ||
369 | } | ||
370 | |||
371 | static void __init octeon_fdt_set_mac_addr(int n, u64 *pmac) | ||
372 | { | ||
373 | u8 new_mac[6]; | ||
374 | u64 mac = *pmac; | ||
375 | int r; | ||
376 | |||
377 | new_mac[0] = (mac >> 40) & 0xff; | ||
378 | new_mac[1] = (mac >> 32) & 0xff; | ||
379 | new_mac[2] = (mac >> 24) & 0xff; | ||
380 | new_mac[3] = (mac >> 16) & 0xff; | ||
381 | new_mac[4] = (mac >> 8) & 0xff; | ||
382 | new_mac[5] = mac & 0xff; | ||
383 | |||
384 | r = fdt_setprop_inplace(initial_boot_params, n, "local-mac-address", | ||
385 | new_mac, sizeof(new_mac)); | ||
386 | |||
387 | if (r) { | ||
388 | pr_err("Setting \"local-mac-address\" failed %d", r); | ||
389 | return; | ||
390 | } | ||
391 | *pmac = mac + 1; | ||
392 | } | ||
393 | |||
394 | static void __init octeon_fdt_rm_ethernet(int node) | ||
395 | { | ||
396 | const __be32 *phy_handle; | ||
397 | |||
398 | phy_handle = fdt_getprop(initial_boot_params, node, "phy-handle", NULL); | ||
399 | if (phy_handle) { | ||
400 | u32 ph = be32_to_cpup(phy_handle); | ||
401 | int p = fdt_node_offset_by_phandle(initial_boot_params, ph); | ||
402 | if (p >= 0) | ||
403 | fdt_nop_node(initial_boot_params, p); | ||
404 | } | ||
405 | fdt_nop_node(initial_boot_params, node); | ||
406 | } | ||
407 | |||
408 | static void __init octeon_fdt_pip_port(int iface, int i, int p, int max, u64 *pmac) | ||
409 | { | ||
410 | char name_buffer[20]; | ||
411 | int eth; | ||
412 | int phy_addr; | ||
413 | int ipd_port; | ||
414 | |||
415 | snprintf(name_buffer, sizeof(name_buffer), "ethernet@%x", p); | ||
416 | eth = fdt_subnode_offset(initial_boot_params, iface, name_buffer); | ||
417 | if (eth < 0) | ||
418 | return; | ||
419 | if (p > max) { | ||
420 | pr_debug("Deleting port %x:%x\n", i, p); | ||
421 | octeon_fdt_rm_ethernet(eth); | ||
422 | return; | ||
423 | } | ||
424 | if (OCTEON_IS_MODEL(OCTEON_CN68XX)) | ||
425 | ipd_port = (0x100 * i) + (0x10 * p) + 0x800; | ||
426 | else | ||
427 | ipd_port = 16 * i + p; | ||
428 | |||
429 | phy_addr = cvmx_helper_board_get_mii_address(ipd_port); | ||
430 | octeon_fdt_set_phy(eth, phy_addr); | ||
431 | octeon_fdt_set_mac_addr(eth, pmac); | ||
432 | } | ||
433 | |||
434 | static void __init octeon_fdt_pip_iface(int pip, int idx, u64 *pmac) | ||
435 | { | ||
436 | char name_buffer[20]; | ||
437 | int iface; | ||
438 | int p; | ||
439 | int count; | ||
440 | |||
441 | count = cvmx_helper_interface_enumerate(idx); | ||
442 | |||
443 | snprintf(name_buffer, sizeof(name_buffer), "interface@%d", idx); | ||
444 | iface = fdt_subnode_offset(initial_boot_params, pip, name_buffer); | ||
445 | if (iface < 0) | ||
446 | return; | ||
447 | |||
448 | for (p = 0; p < 16; p++) | ||
449 | octeon_fdt_pip_port(iface, idx, p, count - 1, pmac); | ||
450 | } | ||
451 | |||
452 | int __init octeon_prune_device_tree(void) | ||
453 | { | ||
454 | int i, max_port, uart_mask; | ||
455 | const char *pip_path; | ||
456 | const char *alias_prop; | ||
457 | char name_buffer[20]; | ||
458 | int aliases; | ||
459 | u64 mac_addr_base; | ||
460 | |||
461 | if (fdt_check_header(initial_boot_params)) | ||
462 | panic("Corrupt Device Tree."); | ||
463 | |||
464 | aliases = fdt_path_offset(initial_boot_params, "/aliases"); | ||
465 | if (aliases < 0) { | ||
466 | pr_err("Error: No /aliases node in device tree."); | ||
467 | return -EINVAL; | ||
468 | } | ||
469 | |||
470 | |||
471 | mac_addr_base = | ||
472 | ((octeon_bootinfo->mac_addr_base[0] & 0xffull)) << 40 | | ||
473 | ((octeon_bootinfo->mac_addr_base[1] & 0xffull)) << 32 | | ||
474 | ((octeon_bootinfo->mac_addr_base[2] & 0xffull)) << 24 | | ||
475 | ((octeon_bootinfo->mac_addr_base[3] & 0xffull)) << 16 | | ||
476 | ((octeon_bootinfo->mac_addr_base[4] & 0xffull)) << 8 | | ||
477 | (octeon_bootinfo->mac_addr_base[5] & 0xffull); | ||
478 | |||
479 | if (OCTEON_IS_MODEL(OCTEON_CN52XX) || OCTEON_IS_MODEL(OCTEON_CN63XX)) | ||
480 | max_port = 2; | ||
481 | else if (OCTEON_IS_MODEL(OCTEON_CN56XX) || OCTEON_IS_MODEL(OCTEON_CN68XX)) | ||
482 | max_port = 1; | ||
483 | else | ||
484 | max_port = 0; | ||
485 | |||
486 | if (octeon_bootinfo->board_type == CVMX_BOARD_TYPE_NIC10E) | ||
487 | max_port = 0; | ||
488 | |||
489 | for (i = 0; i < 2; i++) { | ||
490 | int mgmt; | ||
491 | snprintf(name_buffer, sizeof(name_buffer), | ||
492 | "mix%d", i); | ||
493 | alias_prop = fdt_getprop(initial_boot_params, aliases, | ||
494 | name_buffer, NULL); | ||
495 | if (alias_prop) { | ||
496 | mgmt = fdt_path_offset(initial_boot_params, alias_prop); | ||
497 | if (mgmt < 0) | ||
498 | continue; | ||
499 | if (i >= max_port) { | ||
500 | pr_debug("Deleting mix%d\n", i); | ||
501 | octeon_fdt_rm_ethernet(mgmt); | ||
502 | fdt_nop_property(initial_boot_params, aliases, | ||
503 | name_buffer); | ||
504 | } else { | ||
505 | int phy_addr = cvmx_helper_board_get_mii_address(CVMX_HELPER_BOARD_MGMT_IPD_PORT + i); | ||
506 | octeon_fdt_set_phy(mgmt, phy_addr); | ||
507 | octeon_fdt_set_mac_addr(mgmt, &mac_addr_base); | ||
508 | } | ||
509 | } | ||
510 | } | ||
511 | |||
512 | pip_path = fdt_getprop(initial_boot_params, aliases, "pip", NULL); | ||
513 | if (pip_path) { | ||
514 | int pip = fdt_path_offset(initial_boot_params, pip_path); | ||
515 | if (pip >= 0) | ||
516 | for (i = 0; i <= 4; i++) | ||
517 | octeon_fdt_pip_iface(pip, i, &mac_addr_base); | ||
518 | } | ||
519 | |||
520 | /* I2C */ | ||
521 | if (OCTEON_IS_MODEL(OCTEON_CN52XX) || | ||
522 | OCTEON_IS_MODEL(OCTEON_CN63XX) || | ||
523 | OCTEON_IS_MODEL(OCTEON_CN68XX) || | ||
524 | OCTEON_IS_MODEL(OCTEON_CN56XX)) | ||
525 | max_port = 2; | ||
526 | else | ||
527 | max_port = 1; | ||
528 | |||
529 | for (i = 0; i < 2; i++) { | ||
530 | int i2c; | ||
531 | snprintf(name_buffer, sizeof(name_buffer), | ||
532 | "twsi%d", i); | ||
533 | alias_prop = fdt_getprop(initial_boot_params, aliases, | ||
534 | name_buffer, NULL); | ||
535 | |||
536 | if (alias_prop) { | ||
537 | i2c = fdt_path_offset(initial_boot_params, alias_prop); | ||
538 | if (i2c < 0) | ||
539 | continue; | ||
540 | if (i >= max_port) { | ||
541 | pr_debug("Deleting twsi%d\n", i); | ||
542 | fdt_nop_node(initial_boot_params, i2c); | ||
543 | fdt_nop_property(initial_boot_params, aliases, | ||
544 | name_buffer); | ||
545 | } | ||
546 | } | ||
547 | } | ||
548 | |||
549 | /* SMI/MDIO */ | ||
550 | if (OCTEON_IS_MODEL(OCTEON_CN68XX)) | ||
551 | max_port = 4; | ||
552 | else if (OCTEON_IS_MODEL(OCTEON_CN52XX) || | ||
553 | OCTEON_IS_MODEL(OCTEON_CN63XX) || | ||
554 | OCTEON_IS_MODEL(OCTEON_CN56XX)) | ||
555 | max_port = 2; | ||
556 | else | ||
557 | max_port = 1; | ||
558 | |||
559 | for (i = 0; i < 2; i++) { | ||
560 | int i2c; | ||
561 | snprintf(name_buffer, sizeof(name_buffer), | ||
562 | "smi%d", i); | ||
563 | alias_prop = fdt_getprop(initial_boot_params, aliases, | ||
564 | name_buffer, NULL); | ||
565 | |||
566 | if (alias_prop) { | ||
567 | i2c = fdt_path_offset(initial_boot_params, alias_prop); | ||
568 | if (i2c < 0) | ||
569 | continue; | ||
570 | if (i >= max_port) { | ||
571 | pr_debug("Deleting smi%d\n", i); | ||
572 | fdt_nop_node(initial_boot_params, i2c); | ||
573 | fdt_nop_property(initial_boot_params, aliases, | ||
574 | name_buffer); | ||
575 | } | ||
576 | } | ||
577 | } | ||
578 | |||
579 | /* Serial */ | ||
580 | uart_mask = 3; | ||
581 | |||
582 | /* Right now CN52XX is the only chip with a third uart */ | ||
583 | if (OCTEON_IS_MODEL(OCTEON_CN52XX)) | ||
584 | uart_mask |= 4; /* uart2 */ | ||
585 | |||
586 | for (i = 0; i < 3; i++) { | ||
587 | int uart; | ||
588 | snprintf(name_buffer, sizeof(name_buffer), | ||
589 | "uart%d", i); | ||
590 | alias_prop = fdt_getprop(initial_boot_params, aliases, | ||
591 | name_buffer, NULL); | ||
592 | |||
593 | if (alias_prop) { | ||
594 | uart = fdt_path_offset(initial_boot_params, alias_prop); | ||
595 | if (uart_mask & (1 << i)) | ||
596 | continue; | ||
597 | pr_debug("Deleting uart%d\n", i); | ||
598 | fdt_nop_node(initial_boot_params, uart); | ||
599 | fdt_nop_property(initial_boot_params, aliases, | ||
600 | name_buffer); | ||
601 | } | ||
602 | } | ||
603 | |||
604 | /* Compact Flash */ | ||
605 | alias_prop = fdt_getprop(initial_boot_params, aliases, | ||
606 | "cf0", NULL); | ||
607 | if (alias_prop) { | ||
608 | union cvmx_mio_boot_reg_cfgx mio_boot_reg_cfg; | ||
609 | unsigned long base_ptr, region_base, region_size; | ||
610 | unsigned long region1_base = 0; | ||
611 | unsigned long region1_size = 0; | ||
612 | int cs, bootbus; | ||
613 | bool is_16bit = false; | ||
614 | bool is_true_ide = false; | ||
615 | __be32 new_reg[6]; | ||
616 | __be32 *ranges; | ||
617 | int len; | ||
618 | |||
619 | int cf = fdt_path_offset(initial_boot_params, alias_prop); | ||
620 | base_ptr = 0; | ||
621 | if (octeon_bootinfo->major_version == 1 | ||
622 | && octeon_bootinfo->minor_version >= 1) { | ||
623 | if (octeon_bootinfo->compact_flash_common_base_addr) | ||
624 | base_ptr = octeon_bootinfo->compact_flash_common_base_addr; | ||
625 | } else { | ||
626 | base_ptr = 0x1d000800; | ||
627 | } | ||
628 | |||
629 | if (!base_ptr) | ||
630 | goto no_cf; | ||
631 | |||
632 | /* Find CS0 region. */ | ||
633 | for (cs = 0; cs < 8; cs++) { | ||
634 | mio_boot_reg_cfg.u64 = cvmx_read_csr(CVMX_MIO_BOOT_REG_CFGX(cs)); | ||
635 | region_base = mio_boot_reg_cfg.s.base << 16; | ||
636 | region_size = (mio_boot_reg_cfg.s.size + 1) << 16; | ||
637 | if (mio_boot_reg_cfg.s.en && base_ptr >= region_base | ||
638 | && base_ptr < region_base + region_size) { | ||
639 | is_16bit = mio_boot_reg_cfg.s.width; | ||
640 | break; | ||
641 | } | ||
642 | } | ||
643 | if (cs >= 7) { | ||
644 | /* cs and cs + 1 are CS0 and CS1, both must be less than 8. */ | ||
645 | goto no_cf; | ||
646 | } | ||
647 | |||
648 | if (!(base_ptr & 0xfffful)) { | ||
649 | /* | ||
650 | * Boot loader signals availability of DMA (true_ide | ||
651 | * mode) by setting low order bits of base_ptr to | ||
652 | * zero. | ||
653 | */ | ||
654 | |||
655 | /* Asume that CS1 immediately follows. */ | ||
656 | mio_boot_reg_cfg.u64 = | ||
657 | cvmx_read_csr(CVMX_MIO_BOOT_REG_CFGX(cs + 1)); | ||
658 | region1_base = mio_boot_reg_cfg.s.base << 16; | ||
659 | region1_size = (mio_boot_reg_cfg.s.size + 1) << 16; | ||
660 | if (!mio_boot_reg_cfg.s.en) | ||
661 | goto no_cf; | ||
662 | is_true_ide = true; | ||
663 | |||
664 | } else { | ||
665 | fdt_nop_property(initial_boot_params, cf, "cavium,true-ide"); | ||
666 | fdt_nop_property(initial_boot_params, cf, "cavium,dma-engine-handle"); | ||
667 | if (!is_16bit) { | ||
668 | __be32 width = cpu_to_be32(8); | ||
669 | fdt_setprop_inplace(initial_boot_params, cf, | ||
670 | "cavium,bus-width", &width, sizeof(width)); | ||
671 | } | ||
672 | } | ||
673 | new_reg[0] = cpu_to_be32(cs); | ||
674 | new_reg[1] = cpu_to_be32(0); | ||
675 | new_reg[2] = cpu_to_be32(0x10000); | ||
676 | new_reg[3] = cpu_to_be32(cs + 1); | ||
677 | new_reg[4] = cpu_to_be32(0); | ||
678 | new_reg[5] = cpu_to_be32(0x10000); | ||
679 | fdt_setprop_inplace(initial_boot_params, cf, | ||
680 | "reg", new_reg, sizeof(new_reg)); | ||
681 | |||
682 | bootbus = fdt_parent_offset(initial_boot_params, cf); | ||
683 | if (bootbus < 0) | ||
684 | goto no_cf; | ||
685 | ranges = fdt_getprop_w(initial_boot_params, bootbus, "ranges", &len); | ||
686 | if (!ranges || len < (5 * 8 * sizeof(__be32))) | ||
687 | goto no_cf; | ||
688 | |||
689 | ranges[(cs * 5) + 2] = cpu_to_be32(region_base >> 32); | ||
690 | ranges[(cs * 5) + 3] = cpu_to_be32(region_base & 0xffffffff); | ||
691 | ranges[(cs * 5) + 4] = cpu_to_be32(region_size); | ||
692 | if (is_true_ide) { | ||
693 | cs++; | ||
694 | ranges[(cs * 5) + 2] = cpu_to_be32(region1_base >> 32); | ||
695 | ranges[(cs * 5) + 3] = cpu_to_be32(region1_base & 0xffffffff); | ||
696 | ranges[(cs * 5) + 4] = cpu_to_be32(region1_size); | ||
697 | } | ||
698 | goto end_cf; | ||
699 | no_cf: | ||
700 | fdt_nop_node(initial_boot_params, cf); | ||
701 | |||
702 | end_cf: | ||
703 | ; | ||
704 | } | ||
705 | |||
706 | /* 8 char LED */ | ||
707 | alias_prop = fdt_getprop(initial_boot_params, aliases, | ||
708 | "led0", NULL); | ||
709 | if (alias_prop) { | ||
710 | union cvmx_mio_boot_reg_cfgx mio_boot_reg_cfg; | ||
711 | unsigned long base_ptr, region_base, region_size; | ||
712 | int cs, bootbus; | ||
713 | __be32 new_reg[6]; | ||
714 | __be32 *ranges; | ||
715 | int len; | ||
716 | int led = fdt_path_offset(initial_boot_params, alias_prop); | ||
717 | |||
718 | base_ptr = octeon_bootinfo->led_display_base_addr; | ||
719 | if (base_ptr == 0) | ||
720 | goto no_led; | ||
721 | /* Find CS0 region. */ | ||
722 | for (cs = 0; cs < 8; cs++) { | ||
723 | mio_boot_reg_cfg.u64 = cvmx_read_csr(CVMX_MIO_BOOT_REG_CFGX(cs)); | ||
724 | region_base = mio_boot_reg_cfg.s.base << 16; | ||
725 | region_size = (mio_boot_reg_cfg.s.size + 1) << 16; | ||
726 | if (mio_boot_reg_cfg.s.en && base_ptr >= region_base | ||
727 | && base_ptr < region_base + region_size) | ||
728 | break; | ||
729 | } | ||
730 | |||
731 | if (cs > 7) | ||
732 | goto no_led; | ||
733 | |||
734 | new_reg[0] = cpu_to_be32(cs); | ||
735 | new_reg[1] = cpu_to_be32(0x20); | ||
736 | new_reg[2] = cpu_to_be32(0x20); | ||
737 | new_reg[3] = cpu_to_be32(cs); | ||
738 | new_reg[4] = cpu_to_be32(0); | ||
739 | new_reg[5] = cpu_to_be32(0x20); | ||
740 | fdt_setprop_inplace(initial_boot_params, led, | ||
741 | "reg", new_reg, sizeof(new_reg)); | ||
742 | |||
743 | bootbus = fdt_parent_offset(initial_boot_params, led); | ||
744 | if (bootbus < 0) | ||
745 | goto no_led; | ||
746 | ranges = fdt_getprop_w(initial_boot_params, bootbus, "ranges", &len); | ||
747 | if (!ranges || len < (5 * 8 * sizeof(__be32))) | ||
748 | goto no_led; | ||
749 | |||
750 | ranges[(cs * 5) + 2] = cpu_to_be32(region_base >> 32); | ||
751 | ranges[(cs * 5) + 3] = cpu_to_be32(region_base & 0xffffffff); | ||
752 | ranges[(cs * 5) + 4] = cpu_to_be32(region_size); | ||
753 | goto end_led; | ||
754 | |||
755 | no_led: | ||
756 | fdt_nop_node(initial_boot_params, led); | ||
757 | end_led: | ||
758 | ; | ||
759 | } | ||
760 | |||
761 | /* OHCI/UHCI USB */ | ||
762 | alias_prop = fdt_getprop(initial_boot_params, aliases, | ||
763 | "uctl", NULL); | ||
764 | if (alias_prop) { | ||
765 | int uctl = fdt_path_offset(initial_boot_params, alias_prop); | ||
766 | |||
767 | if (uctl >= 0 && (!OCTEON_IS_MODEL(OCTEON_CN6XXX) || | ||
768 | octeon_bootinfo->board_type == CVMX_BOARD_TYPE_NIC2E)) { | ||
769 | pr_debug("Deleting uctl\n"); | ||
770 | fdt_nop_node(initial_boot_params, uctl); | ||
771 | fdt_nop_property(initial_boot_params, aliases, "uctl"); | ||
772 | } else if (octeon_bootinfo->board_type == CVMX_BOARD_TYPE_NIC10E || | ||
773 | octeon_bootinfo->board_type == CVMX_BOARD_TYPE_NIC4E) { | ||
774 | /* Missing "refclk-type" defaults to crystal. */ | ||
775 | fdt_nop_property(initial_boot_params, uctl, "refclk-type"); | ||
776 | } | ||
777 | } | ||
778 | |||
779 | return 0; | ||
780 | } | ||
781 | |||
782 | static int __init octeon_publish_devices(void) | ||
783 | { | ||
784 | return of_platform_bus_probe(NULL, octeon_ids, NULL); | ||
785 | } | ||
786 | device_initcall(octeon_publish_devices); | ||
787 | |||
443 | MODULE_AUTHOR("David Daney <ddaney@caviumnetworks.com>"); | 788 | MODULE_AUTHOR("David Daney <ddaney@caviumnetworks.com>"); |
444 | MODULE_LICENSE("GPL"); | 789 | MODULE_LICENSE("GPL"); |
445 | MODULE_DESCRIPTION("Platform driver for Octeon SOC"); | 790 | MODULE_DESCRIPTION("Platform driver for Octeon SOC"); |
diff --git a/arch/mips/cavium-octeon/octeon_3xxx.dts b/arch/mips/cavium-octeon/octeon_3xxx.dts new file mode 100644 index 00000000000..f28b2d0fde2 --- /dev/null +++ b/arch/mips/cavium-octeon/octeon_3xxx.dts | |||
@@ -0,0 +1,571 @@ | |||
1 | /dts-v1/; | ||
2 | /* | ||
3 | * OCTEON 3XXX, 5XXX, 63XX device tree skeleton. | ||
4 | * | ||
5 | * This device tree is pruned and patched by early boot code before | ||
6 | * use. Because of this, it contains a super-set of the available | ||
7 | * devices and properties. | ||
8 | */ | ||
9 | / { | ||
10 | compatible = "cavium,octeon-3860"; | ||
11 | #address-cells = <2>; | ||
12 | #size-cells = <2>; | ||
13 | interrupt-parent = <&ciu>; | ||
14 | |||
15 | soc@0 { | ||
16 | compatible = "simple-bus"; | ||
17 | #address-cells = <2>; | ||
18 | #size-cells = <2>; | ||
19 | ranges; /* Direct mapping */ | ||
20 | |||
21 | ciu: interrupt-controller@1070000000000 { | ||
22 | compatible = "cavium,octeon-3860-ciu"; | ||
23 | interrupt-controller; | ||
24 | /* Interrupts are specified by two parts: | ||
25 | * 1) Controller register (0 or 1) | ||
26 | * 2) Bit within the register (0..63) | ||
27 | */ | ||
28 | #interrupt-cells = <2>; | ||
29 | reg = <0x10700 0x00000000 0x0 0x7000>; | ||
30 | }; | ||
31 | |||
32 | gpio: gpio-controller@1070000000800 { | ||
33 | #gpio-cells = <2>; | ||
34 | compatible = "cavium,octeon-3860-gpio"; | ||
35 | reg = <0x10700 0x00000800 0x0 0x100>; | ||
36 | gpio-controller; | ||
37 | /* Interrupts are specified by two parts: | ||
38 | * 1) GPIO pin number (0..15) | ||
39 | * 2) Triggering (1 - edge rising | ||
40 | * 2 - edge falling | ||
41 | * 4 - level active high | ||
42 | * 8 - level active low) | ||
43 | */ | ||
44 | interrupt-controller; | ||
45 | #interrupt-cells = <2>; | ||
46 | /* The GPIO pin connect to 16 consecutive CUI bits */ | ||
47 | interrupts = <0 16>, <0 17>, <0 18>, <0 19>, | ||
48 | <0 20>, <0 21>, <0 22>, <0 23>, | ||
49 | <0 24>, <0 25>, <0 26>, <0 27>, | ||
50 | <0 28>, <0 29>, <0 30>, <0 31>; | ||
51 | }; | ||
52 | |||
53 | smi0: mdio@1180000001800 { | ||
54 | compatible = "cavium,octeon-3860-mdio"; | ||
55 | #address-cells = <1>; | ||
56 | #size-cells = <0>; | ||
57 | reg = <0x11800 0x00001800 0x0 0x40>; | ||
58 | |||
59 | phy0: ethernet-phy@0 { | ||
60 | compatible = "marvell,88e1118"; | ||
61 | marvell,reg-init = | ||
62 | /* Fix rx and tx clock transition timing */ | ||
63 | <2 0x15 0xffcf 0>, /* Reg 2,21 Clear bits 4, 5 */ | ||
64 | /* Adjust LED drive. */ | ||
65 | <3 0x11 0 0x442a>, /* Reg 3,17 <- 0442a */ | ||
66 | /* irq, blink-activity, blink-link */ | ||
67 | <3 0x10 0 0x0242>; /* Reg 3,16 <- 0x0242 */ | ||
68 | reg = <0>; | ||
69 | }; | ||
70 | |||
71 | phy1: ethernet-phy@1 { | ||
72 | compatible = "marvell,88e1118"; | ||
73 | marvell,reg-init = | ||
74 | /* Fix rx and tx clock transition timing */ | ||
75 | <2 0x15 0xffcf 0>, /* Reg 2,21 Clear bits 4, 5 */ | ||
76 | /* Adjust LED drive. */ | ||
77 | <3 0x11 0 0x442a>, /* Reg 3,17 <- 0442a */ | ||
78 | /* irq, blink-activity, blink-link */ | ||
79 | <3 0x10 0 0x0242>; /* Reg 3,16 <- 0x0242 */ | ||
80 | reg = <1>; | ||
81 | }; | ||
82 | |||
83 | phy2: ethernet-phy@2 { | ||
84 | reg = <2>; | ||
85 | compatible = "marvell,88e1149r"; | ||
86 | marvell,reg-init = <3 0x10 0 0x5777>, | ||
87 | <3 0x11 0 0x00aa>, | ||
88 | <3 0x12 0 0x4105>, | ||
89 | <3 0x13 0 0x0a60>; | ||
90 | }; | ||
91 | phy3: ethernet-phy@3 { | ||
92 | reg = <3>; | ||
93 | compatible = "marvell,88e1149r"; | ||
94 | marvell,reg-init = <3 0x10 0 0x5777>, | ||
95 | <3 0x11 0 0x00aa>, | ||
96 | <3 0x12 0 0x4105>, | ||
97 | <3 0x13 0 0x0a60>; | ||
98 | }; | ||
99 | phy4: ethernet-phy@4 { | ||
100 | reg = <4>; | ||
101 | compatible = "marvell,88e1149r"; | ||
102 | marvell,reg-init = <3 0x10 0 0x5777>, | ||
103 | <3 0x11 0 0x00aa>, | ||
104 | <3 0x12 0 0x4105>, | ||
105 | <3 0x13 0 0x0a60>; | ||
106 | }; | ||
107 | phy5: ethernet-phy@5 { | ||
108 | reg = <5>; | ||
109 | compatible = "marvell,88e1149r"; | ||
110 | marvell,reg-init = <3 0x10 0 0x5777>, | ||
111 | <3 0x11 0 0x00aa>, | ||
112 | <3 0x12 0 0x4105>, | ||
113 | <3 0x13 0 0x0a60>; | ||
114 | }; | ||
115 | |||
116 | phy6: ethernet-phy@6 { | ||
117 | reg = <6>; | ||
118 | compatible = "marvell,88e1149r"; | ||
119 | marvell,reg-init = <3 0x10 0 0x5777>, | ||
120 | <3 0x11 0 0x00aa>, | ||
121 | <3 0x12 0 0x4105>, | ||
122 | <3 0x13 0 0x0a60>; | ||
123 | }; | ||
124 | phy7: ethernet-phy@7 { | ||
125 | reg = <7>; | ||
126 | compatible = "marvell,88e1149r"; | ||
127 | marvell,reg-init = <3 0x10 0 0x5777>, | ||
128 | <3 0x11 0 0x00aa>, | ||
129 | <3 0x12 0 0x4105>, | ||
130 | <3 0x13 0 0x0a60>; | ||
131 | }; | ||
132 | phy8: ethernet-phy@8 { | ||
133 | reg = <8>; | ||
134 | compatible = "marvell,88e1149r"; | ||
135 | marvell,reg-init = <3 0x10 0 0x5777>, | ||
136 | <3 0x11 0 0x00aa>, | ||
137 | <3 0x12 0 0x4105>, | ||
138 | <3 0x13 0 0x0a60>; | ||
139 | }; | ||
140 | phy9: ethernet-phy@9 { | ||
141 | reg = <9>; | ||
142 | compatible = "marvell,88e1149r"; | ||
143 | marvell,reg-init = <3 0x10 0 0x5777>, | ||
144 | <3 0x11 0 0x00aa>, | ||
145 | <3 0x12 0 0x4105>, | ||
146 | <3 0x13 0 0x0a60>; | ||
147 | }; | ||
148 | }; | ||
149 | |||
150 | smi1: mdio@1180000001900 { | ||
151 | compatible = "cavium,octeon-3860-mdio"; | ||
152 | #address-cells = <1>; | ||
153 | #size-cells = <0>; | ||
154 | reg = <0x11800 0x00001900 0x0 0x40>; | ||
155 | |||
156 | phy100: ethernet-phy@1 { | ||
157 | reg = <1>; | ||
158 | compatible = "marvell,88e1149r"; | ||
159 | marvell,reg-init = <3 0x10 0 0x5777>, | ||
160 | <3 0x11 0 0x00aa>, | ||
161 | <3 0x12 0 0x4105>, | ||
162 | <3 0x13 0 0x0a60>; | ||
163 | interrupt-parent = <&gpio>; | ||
164 | interrupts = <12 8>; /* Pin 12, active low */ | ||
165 | }; | ||
166 | phy101: ethernet-phy@2 { | ||
167 | reg = <2>; | ||
168 | compatible = "marvell,88e1149r"; | ||
169 | marvell,reg-init = <3 0x10 0 0x5777>, | ||
170 | <3 0x11 0 0x00aa>, | ||
171 | <3 0x12 0 0x4105>, | ||
172 | <3 0x13 0 0x0a60>; | ||
173 | interrupt-parent = <&gpio>; | ||
174 | interrupts = <12 8>; /* Pin 12, active low */ | ||
175 | }; | ||
176 | phy102: ethernet-phy@3 { | ||
177 | reg = <3>; | ||
178 | compatible = "marvell,88e1149r"; | ||
179 | marvell,reg-init = <3 0x10 0 0x5777>, | ||
180 | <3 0x11 0 0x00aa>, | ||
181 | <3 0x12 0 0x4105>, | ||
182 | <3 0x13 0 0x0a60>; | ||
183 | interrupt-parent = <&gpio>; | ||
184 | interrupts = <12 8>; /* Pin 12, active low */ | ||
185 | }; | ||
186 | phy103: ethernet-phy@4 { | ||
187 | reg = <4>; | ||
188 | compatible = "marvell,88e1149r"; | ||
189 | marvell,reg-init = <3 0x10 0 0x5777>, | ||
190 | <3 0x11 0 0x00aa>, | ||
191 | <3 0x12 0 0x4105>, | ||
192 | <3 0x13 0 0x0a60>; | ||
193 | interrupt-parent = <&gpio>; | ||
194 | interrupts = <12 8>; /* Pin 12, active low */ | ||
195 | }; | ||
196 | }; | ||
197 | |||
198 | mix0: ethernet@1070000100000 { | ||
199 | compatible = "cavium,octeon-5750-mix"; | ||
200 | reg = <0x10700 0x00100000 0x0 0x100>, /* MIX */ | ||
201 | <0x11800 0xE0000000 0x0 0x300>, /* AGL */ | ||
202 | <0x11800 0xE0000400 0x0 0x400>, /* AGL_SHARED */ | ||
203 | <0x11800 0xE0002000 0x0 0x8>; /* AGL_PRT_CTL */ | ||
204 | cell-index = <0>; | ||
205 | interrupts = <0 62>, <1 46>; | ||
206 | local-mac-address = [ 00 00 00 00 00 00 ]; | ||
207 | phy-handle = <&phy0>; | ||
208 | }; | ||
209 | |||
210 | mix1: ethernet@1070000100800 { | ||
211 | compatible = "cavium,octeon-5750-mix"; | ||
212 | reg = <0x10700 0x00100800 0x0 0x100>, /* MIX */ | ||
213 | <0x11800 0xE0000800 0x0 0x300>, /* AGL */ | ||
214 | <0x11800 0xE0000400 0x0 0x400>, /* AGL_SHARED */ | ||
215 | <0x11800 0xE0002008 0x0 0x8>; /* AGL_PRT_CTL */ | ||
216 | cell-index = <1>; | ||
217 | interrupts = <1 18>, < 1 46>; | ||
218 | local-mac-address = [ 00 00 00 00 00 00 ]; | ||
219 | phy-handle = <&phy1>; | ||
220 | }; | ||
221 | |||
222 | pip: pip@11800a0000000 { | ||
223 | compatible = "cavium,octeon-3860-pip"; | ||
224 | #address-cells = <1>; | ||
225 | #size-cells = <0>; | ||
226 | reg = <0x11800 0xa0000000 0x0 0x2000>; | ||
227 | |||
228 | interface@0 { | ||
229 | compatible = "cavium,octeon-3860-pip-interface"; | ||
230 | #address-cells = <1>; | ||
231 | #size-cells = <0>; | ||
232 | reg = <0>; /* interface */ | ||
233 | |||
234 | ethernet@0 { | ||
235 | compatible = "cavium,octeon-3860-pip-port"; | ||
236 | reg = <0x0>; /* Port */ | ||
237 | local-mac-address = [ 00 00 00 00 00 00 ]; | ||
238 | phy-handle = <&phy2>; | ||
239 | cavium,alt-phy-handle = <&phy100>; | ||
240 | }; | ||
241 | ethernet@1 { | ||
242 | compatible = "cavium,octeon-3860-pip-port"; | ||
243 | reg = <0x1>; /* Port */ | ||
244 | local-mac-address = [ 00 00 00 00 00 00 ]; | ||
245 | phy-handle = <&phy3>; | ||
246 | cavium,alt-phy-handle = <&phy101>; | ||
247 | }; | ||
248 | ethernet@2 { | ||
249 | compatible = "cavium,octeon-3860-pip-port"; | ||
250 | reg = <0x2>; /* Port */ | ||
251 | local-mac-address = [ 00 00 00 00 00 00 ]; | ||
252 | phy-handle = <&phy4>; | ||
253 | cavium,alt-phy-handle = <&phy102>; | ||
254 | }; | ||
255 | ethernet@3 { | ||
256 | compatible = "cavium,octeon-3860-pip-port"; | ||
257 | reg = <0x3>; /* Port */ | ||
258 | local-mac-address = [ 00 00 00 00 00 00 ]; | ||
259 | phy-handle = <&phy5>; | ||
260 | cavium,alt-phy-handle = <&phy103>; | ||
261 | }; | ||
262 | ethernet@4 { | ||
263 | compatible = "cavium,octeon-3860-pip-port"; | ||
264 | reg = <0x4>; /* Port */ | ||
265 | local-mac-address = [ 00 00 00 00 00 00 ]; | ||
266 | }; | ||
267 | ethernet@5 { | ||
268 | compatible = "cavium,octeon-3860-pip-port"; | ||
269 | reg = <0x5>; /* Port */ | ||
270 | local-mac-address = [ 00 00 00 00 00 00 ]; | ||
271 | }; | ||
272 | ethernet@6 { | ||
273 | compatible = "cavium,octeon-3860-pip-port"; | ||
274 | reg = <0x6>; /* Port */ | ||
275 | local-mac-address = [ 00 00 00 00 00 00 ]; | ||
276 | }; | ||
277 | ethernet@7 { | ||
278 | compatible = "cavium,octeon-3860-pip-port"; | ||
279 | reg = <0x7>; /* Port */ | ||
280 | local-mac-address = [ 00 00 00 00 00 00 ]; | ||
281 | }; | ||
282 | ethernet@8 { | ||
283 | compatible = "cavium,octeon-3860-pip-port"; | ||
284 | reg = <0x8>; /* Port */ | ||
285 | local-mac-address = [ 00 00 00 00 00 00 ]; | ||
286 | }; | ||
287 | ethernet@9 { | ||
288 | compatible = "cavium,octeon-3860-pip-port"; | ||
289 | reg = <0x9>; /* Port */ | ||
290 | local-mac-address = [ 00 00 00 00 00 00 ]; | ||
291 | }; | ||
292 | ethernet@a { | ||
293 | compatible = "cavium,octeon-3860-pip-port"; | ||
294 | reg = <0xa>; /* Port */ | ||
295 | local-mac-address = [ 00 00 00 00 00 00 ]; | ||
296 | }; | ||
297 | ethernet@b { | ||
298 | compatible = "cavium,octeon-3860-pip-port"; | ||
299 | reg = <0xb>; /* Port */ | ||
300 | local-mac-address = [ 00 00 00 00 00 00 ]; | ||
301 | }; | ||
302 | ethernet@c { | ||
303 | compatible = "cavium,octeon-3860-pip-port"; | ||
304 | reg = <0xc>; /* Port */ | ||
305 | local-mac-address = [ 00 00 00 00 00 00 ]; | ||
306 | }; | ||
307 | ethernet@d { | ||
308 | compatible = "cavium,octeon-3860-pip-port"; | ||
309 | reg = <0xd>; /* Port */ | ||
310 | local-mac-address = [ 00 00 00 00 00 00 ]; | ||
311 | }; | ||
312 | ethernet@e { | ||
313 | compatible = "cavium,octeon-3860-pip-port"; | ||
314 | reg = <0xe>; /* Port */ | ||
315 | local-mac-address = [ 00 00 00 00 00 00 ]; | ||
316 | }; | ||
317 | ethernet@f { | ||
318 | compatible = "cavium,octeon-3860-pip-port"; | ||
319 | reg = <0xf>; /* Port */ | ||
320 | local-mac-address = [ 00 00 00 00 00 00 ]; | ||
321 | }; | ||
322 | }; | ||
323 | |||
324 | interface@1 { | ||
325 | compatible = "cavium,octeon-3860-pip-interface"; | ||
326 | #address-cells = <1>; | ||
327 | #size-cells = <0>; | ||
328 | reg = <1>; /* interface */ | ||
329 | |||
330 | ethernet@0 { | ||
331 | compatible = "cavium,octeon-3860-pip-port"; | ||
332 | reg = <0x0>; /* Port */ | ||
333 | local-mac-address = [ 00 00 00 00 00 00 ]; | ||
334 | phy-handle = <&phy6>; | ||
335 | }; | ||
336 | ethernet@1 { | ||
337 | compatible = "cavium,octeon-3860-pip-port"; | ||
338 | reg = <0x1>; /* Port */ | ||
339 | local-mac-address = [ 00 00 00 00 00 00 ]; | ||
340 | phy-handle = <&phy7>; | ||
341 | }; | ||
342 | ethernet@2 { | ||
343 | compatible = "cavium,octeon-3860-pip-port"; | ||
344 | reg = <0x2>; /* Port */ | ||
345 | local-mac-address = [ 00 00 00 00 00 00 ]; | ||
346 | phy-handle = <&phy8>; | ||
347 | }; | ||
348 | ethernet@3 { | ||
349 | compatible = "cavium,octeon-3860-pip-port"; | ||
350 | reg = <0x3>; /* Port */ | ||
351 | local-mac-address = [ 00 00 00 00 00 00 ]; | ||
352 | phy-handle = <&phy9>; | ||
353 | }; | ||
354 | }; | ||
355 | }; | ||
356 | |||
357 | twsi0: i2c@1180000001000 { | ||
358 | #address-cells = <1>; | ||
359 | #size-cells = <0>; | ||
360 | compatible = "cavium,octeon-3860-twsi"; | ||
361 | reg = <0x11800 0x00001000 0x0 0x200>; | ||
362 | interrupts = <0 45>; | ||
363 | clock-frequency = <100000>; | ||
364 | |||
365 | rtc@68 { | ||
366 | compatible = "dallas,ds1337"; | ||
367 | reg = <0x68>; | ||
368 | }; | ||
369 | tmp@4c { | ||
370 | compatible = "ti,tmp421"; | ||
371 | reg = <0x4c>; | ||
372 | }; | ||
373 | }; | ||
374 | |||
375 | twsi1: i2c@1180000001200 { | ||
376 | #address-cells = <1>; | ||
377 | #size-cells = <0>; | ||
378 | compatible = "cavium,octeon-3860-twsi"; | ||
379 | reg = <0x11800 0x00001200 0x0 0x200>; | ||
380 | interrupts = <0 59>; | ||
381 | clock-frequency = <100000>; | ||
382 | }; | ||
383 | |||
384 | uart0: serial@1180000000800 { | ||
385 | compatible = "cavium,octeon-3860-uart","ns16550"; | ||
386 | reg = <0x11800 0x00000800 0x0 0x400>; | ||
387 | clock-frequency = <0>; | ||
388 | current-speed = <115200>; | ||
389 | reg-shift = <3>; | ||
390 | interrupts = <0 34>; | ||
391 | }; | ||
392 | |||
393 | uart1: serial@1180000000c00 { | ||
394 | compatible = "cavium,octeon-3860-uart","ns16550"; | ||
395 | reg = <0x11800 0x00000c00 0x0 0x400>; | ||
396 | clock-frequency = <0>; | ||
397 | current-speed = <115200>; | ||
398 | reg-shift = <3>; | ||
399 | interrupts = <0 35>; | ||
400 | }; | ||
401 | |||
402 | uart2: serial@1180000000400 { | ||
403 | compatible = "cavium,octeon-3860-uart","ns16550"; | ||
404 | reg = <0x11800 0x00000400 0x0 0x400>; | ||
405 | clock-frequency = <0>; | ||
406 | current-speed = <115200>; | ||
407 | reg-shift = <3>; | ||
408 | interrupts = <1 16>; | ||
409 | }; | ||
410 | |||
411 | bootbus: bootbus@1180000000000 { | ||
412 | compatible = "cavium,octeon-3860-bootbus"; | ||
413 | reg = <0x11800 0x00000000 0x0 0x200>; | ||
414 | /* The chip select number and offset */ | ||
415 | #address-cells = <2>; | ||
416 | /* The size of the chip select region */ | ||
417 | #size-cells = <1>; | ||
418 | ranges = <0 0 0x0 0x1f400000 0xc00000>, | ||
419 | <1 0 0x10000 0x30000000 0>, | ||
420 | <2 0 0x10000 0x40000000 0>, | ||
421 | <3 0 0x10000 0x50000000 0>, | ||
422 | <4 0 0x0 0x1d020000 0x10000>, | ||
423 | <5 0 0x0 0x1d040000 0x10000>, | ||
424 | <6 0 0x0 0x1d050000 0x10000>, | ||
425 | <7 0 0x10000 0x90000000 0>; | ||
426 | |||
427 | cavium,cs-config@0 { | ||
428 | compatible = "cavium,octeon-3860-bootbus-config"; | ||
429 | cavium,cs-index = <0>; | ||
430 | cavium,t-adr = <20>; | ||
431 | cavium,t-ce = <60>; | ||
432 | cavium,t-oe = <60>; | ||
433 | cavium,t-we = <45>; | ||
434 | cavium,t-rd-hld = <35>; | ||
435 | cavium,t-wr-hld = <45>; | ||
436 | cavium,t-pause = <0>; | ||
437 | cavium,t-wait = <0>; | ||
438 | cavium,t-page = <35>; | ||
439 | cavium,t-rd-dly = <0>; | ||
440 | |||
441 | cavium,pages = <0>; | ||
442 | cavium,bus-width = <8>; | ||
443 | }; | ||
444 | cavium,cs-config@4 { | ||
445 | compatible = "cavium,octeon-3860-bootbus-config"; | ||
446 | cavium,cs-index = <4>; | ||
447 | cavium,t-adr = <320>; | ||
448 | cavium,t-ce = <320>; | ||
449 | cavium,t-oe = <320>; | ||
450 | cavium,t-we = <320>; | ||
451 | cavium,t-rd-hld = <320>; | ||
452 | cavium,t-wr-hld = <320>; | ||
453 | cavium,t-pause = <320>; | ||
454 | cavium,t-wait = <320>; | ||
455 | cavium,t-page = <320>; | ||
456 | cavium,t-rd-dly = <0>; | ||
457 | |||
458 | cavium,pages = <0>; | ||
459 | cavium,bus-width = <8>; | ||
460 | }; | ||
461 | cavium,cs-config@5 { | ||
462 | compatible = "cavium,octeon-3860-bootbus-config"; | ||
463 | cavium,cs-index = <5>; | ||
464 | cavium,t-adr = <5>; | ||
465 | cavium,t-ce = <300>; | ||
466 | cavium,t-oe = <125>; | ||
467 | cavium,t-we = <150>; | ||
468 | cavium,t-rd-hld = <100>; | ||
469 | cavium,t-wr-hld = <30>; | ||
470 | cavium,t-pause = <0>; | ||
471 | cavium,t-wait = <30>; | ||
472 | cavium,t-page = <320>; | ||
473 | cavium,t-rd-dly = <0>; | ||
474 | |||
475 | cavium,pages = <0>; | ||
476 | cavium,bus-width = <16>; | ||
477 | }; | ||
478 | cavium,cs-config@6 { | ||
479 | compatible = "cavium,octeon-3860-bootbus-config"; | ||
480 | cavium,cs-index = <6>; | ||
481 | cavium,t-adr = <5>; | ||
482 | cavium,t-ce = <300>; | ||
483 | cavium,t-oe = <270>; | ||
484 | cavium,t-we = <150>; | ||
485 | cavium,t-rd-hld = <100>; | ||
486 | cavium,t-wr-hld = <70>; | ||
487 | cavium,t-pause = <0>; | ||
488 | cavium,t-wait = <0>; | ||
489 | cavium,t-page = <320>; | ||
490 | cavium,t-rd-dly = <0>; | ||
491 | |||
492 | cavium,pages = <0>; | ||
493 | cavium,wait-mode; | ||
494 | cavium,bus-width = <16>; | ||
495 | }; | ||
496 | |||
497 | flash0: nor@0,0 { | ||
498 | compatible = "cfi-flash"; | ||
499 | reg = <0 0 0x800000>; | ||
500 | #address-cells = <1>; | ||
501 | #size-cells = <1>; | ||
502 | }; | ||
503 | |||
504 | led0: led-display@4,0 { | ||
505 | compatible = "avago,hdsp-253x"; | ||
506 | reg = <4 0x20 0x20>, <4 0 0x20>; | ||
507 | }; | ||
508 | |||
509 | cf0: compact-flash@5,0 { | ||
510 | compatible = "cavium,ebt3000-compact-flash"; | ||
511 | reg = <5 0 0x10000>, <6 0 0x10000>; | ||
512 | cavium,bus-width = <16>; | ||
513 | cavium,true-ide; | ||
514 | cavium,dma-engine-handle = <&dma0>; | ||
515 | }; | ||
516 | }; | ||
517 | |||
518 | dma0: dma-engine@1180000000100 { | ||
519 | compatible = "cavium,octeon-5750-bootbus-dma"; | ||
520 | reg = <0x11800 0x00000100 0x0 0x8>; | ||
521 | interrupts = <0 63>; | ||
522 | }; | ||
523 | dma1: dma-engine@1180000000108 { | ||
524 | compatible = "cavium,octeon-5750-bootbus-dma"; | ||
525 | reg = <0x11800 0x00000108 0x0 0x8>; | ||
526 | interrupts = <0 63>; | ||
527 | }; | ||
528 | |||
529 | uctl: uctl@118006f000000 { | ||
530 | compatible = "cavium,octeon-6335-uctl"; | ||
531 | reg = <0x11800 0x6f000000 0x0 0x100>; | ||
532 | ranges; /* Direct mapping */ | ||
533 | #address-cells = <2>; | ||
534 | #size-cells = <2>; | ||
535 | /* 12MHz, 24MHz and 48MHz allowed */ | ||
536 | refclk-frequency = <12000000>; | ||
537 | /* Either "crystal" or "external" */ | ||
538 | refclk-type = "crystal"; | ||
539 | |||
540 | ehci@16f0000000000 { | ||
541 | compatible = "cavium,octeon-6335-ehci","usb-ehci"; | ||
542 | reg = <0x16f00 0x00000000 0x0 0x100>; | ||
543 | interrupts = <0 56>; | ||
544 | big-endian-regs; | ||
545 | }; | ||
546 | ohci@16f0000000400 { | ||
547 | compatible = "cavium,octeon-6335-ohci","usb-ohci"; | ||
548 | reg = <0x16f00 0x00000400 0x0 0x100>; | ||
549 | interrupts = <0 56>; | ||
550 | big-endian-regs; | ||
551 | }; | ||
552 | }; | ||
553 | }; | ||
554 | |||
555 | aliases { | ||
556 | mix0 = &mix0; | ||
557 | mix1 = &mix1; | ||
558 | pip = &pip; | ||
559 | smi0 = &smi0; | ||
560 | smi1 = &smi1; | ||
561 | twsi0 = &twsi0; | ||
562 | twsi1 = &twsi1; | ||
563 | uart0 = &uart0; | ||
564 | uart1 = &uart1; | ||
565 | uart2 = &uart2; | ||
566 | flash0 = &flash0; | ||
567 | cf0 = &cf0; | ||
568 | uctl = &uctl; | ||
569 | led0 = &led0; | ||
570 | }; | ||
571 | }; | ||
diff --git a/arch/mips/cavium-octeon/octeon_68xx.dts b/arch/mips/cavium-octeon/octeon_68xx.dts new file mode 100644 index 00000000000..1839468932b --- /dev/null +++ b/arch/mips/cavium-octeon/octeon_68xx.dts | |||
@@ -0,0 +1,625 @@ | |||
1 | /dts-v1/; | ||
2 | /* | ||
3 | * OCTEON 68XX device tree skeleton. | ||
4 | * | ||
5 | * This device tree is pruned and patched by early boot code before | ||
6 | * use. Because of this, it contains a super-set of the available | ||
7 | * devices and properties. | ||
8 | */ | ||
9 | / { | ||
10 | compatible = "cavium,octeon-6880"; | ||
11 | #address-cells = <2>; | ||
12 | #size-cells = <2>; | ||
13 | interrupt-parent = <&ciu2>; | ||
14 | |||
15 | soc@0 { | ||
16 | compatible = "simple-bus"; | ||
17 | #address-cells = <2>; | ||
18 | #size-cells = <2>; | ||
19 | ranges; /* Direct mapping */ | ||
20 | |||
21 | ciu2: interrupt-controller@1070100000000 { | ||
22 | compatible = "cavium,octeon-6880-ciu2"; | ||
23 | interrupt-controller; | ||
24 | /* Interrupts are specified by two parts: | ||
25 | * 1) Controller register (0 or 7) | ||
26 | * 2) Bit within the register (0..63) | ||
27 | */ | ||
28 | #address-cells = <0>; | ||
29 | #interrupt-cells = <2>; | ||
30 | reg = <0x10701 0x00000000 0x0 0x4000000>; | ||
31 | }; | ||
32 | |||
33 | gpio: gpio-controller@1070000000800 { | ||
34 | #gpio-cells = <2>; | ||
35 | compatible = "cavium,octeon-3860-gpio"; | ||
36 | reg = <0x10700 0x00000800 0x0 0x100>; | ||
37 | gpio-controller; | ||
38 | /* Interrupts are specified by two parts: | ||
39 | * 1) GPIO pin number (0..15) | ||
40 | * 2) Triggering (1 - edge rising | ||
41 | * 2 - edge falling | ||
42 | * 4 - level active high | ||
43 | * 8 - level active low) | ||
44 | */ | ||
45 | interrupt-controller; | ||
46 | #interrupt-cells = <2>; | ||
47 | /* The GPIO pins connect to 16 consecutive CUI bits */ | ||
48 | interrupts = <7 0>, <7 1>, <7 2>, <7 3>, | ||
49 | <7 4>, <7 5>, <7 6>, <7 7>, | ||
50 | <7 8>, <7 9>, <7 10>, <7 11>, | ||
51 | <7 12>, <7 13>, <7 14>, <7 15>; | ||
52 | }; | ||
53 | |||
54 | smi0: mdio@1180000003800 { | ||
55 | compatible = "cavium,octeon-3860-mdio"; | ||
56 | #address-cells = <1>; | ||
57 | #size-cells = <0>; | ||
58 | reg = <0x11800 0x00003800 0x0 0x40>; | ||
59 | |||
60 | phy0: ethernet-phy@6 { | ||
61 | compatible = "marvell,88e1118"; | ||
62 | marvell,reg-init = | ||
63 | /* Fix rx and tx clock transition timing */ | ||
64 | <2 0x15 0xffcf 0>, /* Reg 2,21 Clear bits 4, 5 */ | ||
65 | /* Adjust LED drive. */ | ||
66 | <3 0x11 0 0x442a>, /* Reg 3,17 <- 0442a */ | ||
67 | /* irq, blink-activity, blink-link */ | ||
68 | <3 0x10 0 0x0242>; /* Reg 3,16 <- 0x0242 */ | ||
69 | reg = <6>; | ||
70 | }; | ||
71 | |||
72 | phy1: ethernet-phy@1 { | ||
73 | cavium,qlm-trim = "4,sgmii"; | ||
74 | reg = <1>; | ||
75 | compatible = "marvell,88e1149r"; | ||
76 | marvell,reg-init = <3 0x10 0 0x5777>, | ||
77 | <3 0x11 0 0x00aa>, | ||
78 | <3 0x12 0 0x4105>, | ||
79 | <3 0x13 0 0x0a60>; | ||
80 | }; | ||
81 | phy2: ethernet-phy@2 { | ||
82 | cavium,qlm-trim = "4,sgmii"; | ||
83 | reg = <2>; | ||
84 | compatible = "marvell,88e1149r"; | ||
85 | marvell,reg-init = <3 0x10 0 0x5777>, | ||
86 | <3 0x11 0 0x00aa>, | ||
87 | <3 0x12 0 0x4105>, | ||
88 | <3 0x13 0 0x0a60>; | ||
89 | }; | ||
90 | phy3: ethernet-phy@3 { | ||
91 | cavium,qlm-trim = "4,sgmii"; | ||
92 | reg = <3>; | ||
93 | compatible = "marvell,88e1149r"; | ||
94 | marvell,reg-init = <3 0x10 0 0x5777>, | ||
95 | <3 0x11 0 0x00aa>, | ||
96 | <3 0x12 0 0x4105>, | ||
97 | <3 0x13 0 0x0a60>; | ||
98 | }; | ||
99 | phy4: ethernet-phy@4 { | ||
100 | cavium,qlm-trim = "4,sgmii"; | ||
101 | reg = <4>; | ||
102 | compatible = "marvell,88e1149r"; | ||
103 | marvell,reg-init = <3 0x10 0 0x5777>, | ||
104 | <3 0x11 0 0x00aa>, | ||
105 | <3 0x12 0 0x4105>, | ||
106 | <3 0x13 0 0x0a60>; | ||
107 | }; | ||
108 | }; | ||
109 | |||
110 | smi1: mdio@1180000003880 { | ||
111 | compatible = "cavium,octeon-3860-mdio"; | ||
112 | #address-cells = <1>; | ||
113 | #size-cells = <0>; | ||
114 | reg = <0x11800 0x00003880 0x0 0x40>; | ||
115 | |||
116 | phy41: ethernet-phy@1 { | ||
117 | cavium,qlm-trim = "0,sgmii"; | ||
118 | reg = <1>; | ||
119 | compatible = "marvell,88e1149r"; | ||
120 | marvell,reg-init = <3 0x10 0 0x5777>, | ||
121 | <3 0x11 0 0x00aa>, | ||
122 | <3 0x12 0 0x4105>, | ||
123 | <3 0x13 0 0x0a60>; | ||
124 | }; | ||
125 | phy42: ethernet-phy@2 { | ||
126 | cavium,qlm-trim = "0,sgmii"; | ||
127 | reg = <2>; | ||
128 | compatible = "marvell,88e1149r"; | ||
129 | marvell,reg-init = <3 0x10 0 0x5777>, | ||
130 | <3 0x11 0 0x00aa>, | ||
131 | <3 0x12 0 0x4105>, | ||
132 | <3 0x13 0 0x0a60>; | ||
133 | }; | ||
134 | phy43: ethernet-phy@3 { | ||
135 | cavium,qlm-trim = "0,sgmii"; | ||
136 | reg = <3>; | ||
137 | compatible = "marvell,88e1149r"; | ||
138 | marvell,reg-init = <3 0x10 0 0x5777>, | ||
139 | <3 0x11 0 0x00aa>, | ||
140 | <3 0x12 0 0x4105>, | ||
141 | <3 0x13 0 0x0a60>; | ||
142 | }; | ||
143 | phy44: ethernet-phy@4 { | ||
144 | cavium,qlm-trim = "0,sgmii"; | ||
145 | reg = <4>; | ||
146 | compatible = "marvell,88e1149r"; | ||
147 | marvell,reg-init = <3 0x10 0 0x5777>, | ||
148 | <3 0x11 0 0x00aa>, | ||
149 | <3 0x12 0 0x4105>, | ||
150 | <3 0x13 0 0x0a60>; | ||
151 | }; | ||
152 | }; | ||
153 | |||
154 | smi2: mdio@1180000003900 { | ||
155 | compatible = "cavium,octeon-3860-mdio"; | ||
156 | #address-cells = <1>; | ||
157 | #size-cells = <0>; | ||
158 | reg = <0x11800 0x00003900 0x0 0x40>; | ||
159 | |||
160 | phy21: ethernet-phy@1 { | ||
161 | cavium,qlm-trim = "2,sgmii"; | ||
162 | reg = <1>; | ||
163 | compatible = "marvell,88e1149r"; | ||
164 | marvell,reg-init = <3 0x10 0 0x5777>, | ||
165 | <3 0x11 0 0x00aa>, | ||
166 | <3 0x12 0 0x4105>, | ||
167 | <3 0x13 0 0x0a60>; | ||
168 | }; | ||
169 | phy22: ethernet-phy@2 { | ||
170 | cavium,qlm-trim = "2,sgmii"; | ||
171 | reg = <2>; | ||
172 | compatible = "marvell,88e1149r"; | ||
173 | marvell,reg-init = <3 0x10 0 0x5777>, | ||
174 | <3 0x11 0 0x00aa>, | ||
175 | <3 0x12 0 0x4105>, | ||
176 | <3 0x13 0 0x0a60>; | ||
177 | }; | ||
178 | phy23: ethernet-phy@3 { | ||
179 | cavium,qlm-trim = "2,sgmii"; | ||
180 | reg = <3>; | ||
181 | compatible = "marvell,88e1149r"; | ||
182 | marvell,reg-init = <3 0x10 0 0x5777>, | ||
183 | <3 0x11 0 0x00aa>, | ||
184 | <3 0x12 0 0x4105>, | ||
185 | <3 0x13 0 0x0a60>; | ||
186 | }; | ||
187 | phy24: ethernet-phy@4 { | ||
188 | cavium,qlm-trim = "2,sgmii"; | ||
189 | reg = <4>; | ||
190 | compatible = "marvell,88e1149r"; | ||
191 | marvell,reg-init = <3 0x10 0 0x5777>, | ||
192 | <3 0x11 0 0x00aa>, | ||
193 | <3 0x12 0 0x4105>, | ||
194 | <3 0x13 0 0x0a60>; | ||
195 | }; | ||
196 | }; | ||
197 | |||
198 | smi3: mdio@1180000003980 { | ||
199 | compatible = "cavium,octeon-3860-mdio"; | ||
200 | #address-cells = <1>; | ||
201 | #size-cells = <0>; | ||
202 | reg = <0x11800 0x00003980 0x0 0x40>; | ||
203 | |||
204 | phy11: ethernet-phy@1 { | ||
205 | cavium,qlm-trim = "3,sgmii"; | ||
206 | reg = <1>; | ||
207 | compatible = "marvell,88e1149r"; | ||
208 | marvell,reg-init = <3 0x10 0 0x5777>, | ||
209 | <3 0x11 0 0x00aa>, | ||
210 | <3 0x12 0 0x4105>, | ||
211 | <3 0x13 0 0x0a60>; | ||
212 | }; | ||
213 | phy12: ethernet-phy@2 { | ||
214 | cavium,qlm-trim = "3,sgmii"; | ||
215 | reg = <2>; | ||
216 | compatible = "marvell,88e1149r"; | ||
217 | marvell,reg-init = <3 0x10 0 0x5777>, | ||
218 | <3 0x11 0 0x00aa>, | ||
219 | <3 0x12 0 0x4105>, | ||
220 | <3 0x13 0 0x0a60>; | ||
221 | }; | ||
222 | phy13: ethernet-phy@3 { | ||
223 | cavium,qlm-trim = "3,sgmii"; | ||
224 | reg = <3>; | ||
225 | compatible = "marvell,88e1149r"; | ||
226 | marvell,reg-init = <3 0x10 0 0x5777>, | ||
227 | <3 0x11 0 0x00aa>, | ||
228 | <3 0x12 0 0x4105>, | ||
229 | <3 0x13 0 0x0a60>; | ||
230 | }; | ||
231 | phy14: ethernet-phy@4 { | ||
232 | cavium,qlm-trim = "3,sgmii"; | ||
233 | reg = <4>; | ||
234 | compatible = "marvell,88e1149r"; | ||
235 | marvell,reg-init = <3 0x10 0 0x5777>, | ||
236 | <3 0x11 0 0x00aa>, | ||
237 | <3 0x12 0 0x4105>, | ||
238 | <3 0x13 0 0x0a60>; | ||
239 | }; | ||
240 | }; | ||
241 | |||
242 | mix0: ethernet@1070000100000 { | ||
243 | compatible = "cavium,octeon-5750-mix"; | ||
244 | reg = <0x10700 0x00100000 0x0 0x100>, /* MIX */ | ||
245 | <0x11800 0xE0000000 0x0 0x300>, /* AGL */ | ||
246 | <0x11800 0xE0000400 0x0 0x400>, /* AGL_SHARED */ | ||
247 | <0x11800 0xE0002000 0x0 0x8>; /* AGL_PRT_CTL */ | ||
248 | cell-index = <0>; | ||
249 | interrupts = <6 40>, <6 32>; | ||
250 | local-mac-address = [ 00 00 00 00 00 00 ]; | ||
251 | phy-handle = <&phy0>; | ||
252 | }; | ||
253 | |||
254 | pip: pip@11800a0000000 { | ||
255 | compatible = "cavium,octeon-3860-pip"; | ||
256 | #address-cells = <1>; | ||
257 | #size-cells = <0>; | ||
258 | reg = <0x11800 0xa0000000 0x0 0x2000>; | ||
259 | |||
260 | interface@4 { | ||
261 | compatible = "cavium,octeon-3860-pip-interface"; | ||
262 | #address-cells = <1>; | ||
263 | #size-cells = <0>; | ||
264 | reg = <0x4>; /* interface */ | ||
265 | |||
266 | ethernet@0 { | ||
267 | compatible = "cavium,octeon-3860-pip-port"; | ||
268 | reg = <0x0>; /* Port */ | ||
269 | local-mac-address = [ 00 00 00 00 00 00 ]; | ||
270 | phy-handle = <&phy1>; | ||
271 | }; | ||
272 | ethernet@1 { | ||
273 | compatible = "cavium,octeon-3860-pip-port"; | ||
274 | reg = <0x1>; /* Port */ | ||
275 | local-mac-address = [ 00 00 00 00 00 00 ]; | ||
276 | phy-handle = <&phy2>; | ||
277 | }; | ||
278 | ethernet@2 { | ||
279 | compatible = "cavium,octeon-3860-pip-port"; | ||
280 | reg = <0x2>; /* Port */ | ||
281 | local-mac-address = [ 00 00 00 00 00 00 ]; | ||
282 | phy-handle = <&phy3>; | ||
283 | }; | ||
284 | ethernet@3 { | ||
285 | compatible = "cavium,octeon-3860-pip-port"; | ||
286 | reg = <0x3>; /* Port */ | ||
287 | local-mac-address = [ 00 00 00 00 00 00 ]; | ||
288 | phy-handle = <&phy4>; | ||
289 | }; | ||
290 | }; | ||
291 | |||
292 | interface@3 { | ||
293 | compatible = "cavium,octeon-3860-pip-interface"; | ||
294 | #address-cells = <1>; | ||
295 | #size-cells = <0>; | ||
296 | reg = <0x3>; /* interface */ | ||
297 | |||
298 | ethernet@0 { | ||
299 | compatible = "cavium,octeon-3860-pip-port"; | ||
300 | reg = <0x0>; /* Port */ | ||
301 | local-mac-address = [ 00 00 00 00 00 00 ]; | ||
302 | phy-handle = <&phy11>; | ||
303 | }; | ||
304 | ethernet@1 { | ||
305 | compatible = "cavium,octeon-3860-pip-port"; | ||
306 | reg = <0x1>; /* Port */ | ||
307 | local-mac-address = [ 00 00 00 00 00 00 ]; | ||
308 | phy-handle = <&phy12>; | ||
309 | }; | ||
310 | ethernet@2 { | ||
311 | compatible = "cavium,octeon-3860-pip-port"; | ||
312 | reg = <0x2>; /* Port */ | ||
313 | local-mac-address = [ 00 00 00 00 00 00 ]; | ||
314 | phy-handle = <&phy13>; | ||
315 | }; | ||
316 | ethernet@3 { | ||
317 | compatible = "cavium,octeon-3860-pip-port"; | ||
318 | reg = <0x3>; /* Port */ | ||
319 | local-mac-address = [ 00 00 00 00 00 00 ]; | ||
320 | phy-handle = <&phy14>; | ||
321 | }; | ||
322 | }; | ||
323 | |||
324 | interface@2 { | ||
325 | compatible = "cavium,octeon-3860-pip-interface"; | ||
326 | #address-cells = <1>; | ||
327 | #size-cells = <0>; | ||
328 | reg = <0x2>; /* interface */ | ||
329 | |||
330 | ethernet@0 { | ||
331 | compatible = "cavium,octeon-3860-pip-port"; | ||
332 | reg = <0x0>; /* Port */ | ||
333 | local-mac-address = [ 00 00 00 00 00 00 ]; | ||
334 | phy-handle = <&phy21>; | ||
335 | }; | ||
336 | ethernet@1 { | ||
337 | compatible = "cavium,octeon-3860-pip-port"; | ||
338 | reg = <0x1>; /* Port */ | ||
339 | local-mac-address = [ 00 00 00 00 00 00 ]; | ||
340 | phy-handle = <&phy22>; | ||
341 | }; | ||
342 | ethernet@2 { | ||
343 | compatible = "cavium,octeon-3860-pip-port"; | ||
344 | reg = <0x2>; /* Port */ | ||
345 | local-mac-address = [ 00 00 00 00 00 00 ]; | ||
346 | phy-handle = <&phy23>; | ||
347 | }; | ||
348 | ethernet@3 { | ||
349 | compatible = "cavium,octeon-3860-pip-port"; | ||
350 | reg = <0x3>; /* Port */ | ||
351 | local-mac-address = [ 00 00 00 00 00 00 ]; | ||
352 | phy-handle = <&phy24>; | ||
353 | }; | ||
354 | }; | ||
355 | |||
356 | interface@1 { | ||
357 | compatible = "cavium,octeon-3860-pip-interface"; | ||
358 | #address-cells = <1>; | ||
359 | #size-cells = <0>; | ||
360 | reg = <0x1>; /* interface */ | ||
361 | |||
362 | ethernet@0 { | ||
363 | compatible = "cavium,octeon-3860-pip-port"; | ||
364 | reg = <0x0>; /* Port */ | ||
365 | local-mac-address = [ 00 00 00 00 00 00 ]; | ||
366 | }; | ||
367 | }; | ||
368 | |||
369 | interface@0 { | ||
370 | compatible = "cavium,octeon-3860-pip-interface"; | ||
371 | #address-cells = <1>; | ||
372 | #size-cells = <0>; | ||
373 | reg = <0x0>; /* interface */ | ||
374 | |||
375 | ethernet@0 { | ||
376 | compatible = "cavium,octeon-3860-pip-port"; | ||
377 | reg = <0x0>; /* Port */ | ||
378 | local-mac-address = [ 00 00 00 00 00 00 ]; | ||
379 | phy-handle = <&phy41>; | ||
380 | }; | ||
381 | ethernet@1 { | ||
382 | compatible = "cavium,octeon-3860-pip-port"; | ||
383 | reg = <0x1>; /* Port */ | ||
384 | local-mac-address = [ 00 00 00 00 00 00 ]; | ||
385 | phy-handle = <&phy42>; | ||
386 | }; | ||
387 | ethernet@2 { | ||
388 | compatible = "cavium,octeon-3860-pip-port"; | ||
389 | reg = <0x2>; /* Port */ | ||
390 | local-mac-address = [ 00 00 00 00 00 00 ]; | ||
391 | phy-handle = <&phy43>; | ||
392 | }; | ||
393 | ethernet@3 { | ||
394 | compatible = "cavium,octeon-3860-pip-port"; | ||
395 | reg = <0x3>; /* Port */ | ||
396 | local-mac-address = [ 00 00 00 00 00 00 ]; | ||
397 | phy-handle = <&phy44>; | ||
398 | }; | ||
399 | }; | ||
400 | }; | ||
401 | |||
402 | twsi0: i2c@1180000001000 { | ||
403 | #address-cells = <1>; | ||
404 | #size-cells = <0>; | ||
405 | compatible = "cavium,octeon-3860-twsi"; | ||
406 | reg = <0x11800 0x00001000 0x0 0x200>; | ||
407 | interrupts = <3 32>; | ||
408 | clock-frequency = <100000>; | ||
409 | |||
410 | rtc@68 { | ||
411 | compatible = "dallas,ds1337"; | ||
412 | reg = <0x68>; | ||
413 | }; | ||
414 | tmp@4c { | ||
415 | compatible = "ti,tmp421"; | ||
416 | reg = <0x4c>; | ||
417 | }; | ||
418 | }; | ||
419 | |||
420 | twsi1: i2c@1180000001200 { | ||
421 | #address-cells = <1>; | ||
422 | #size-cells = <0>; | ||
423 | compatible = "cavium,octeon-3860-twsi"; | ||
424 | reg = <0x11800 0x00001200 0x0 0x200>; | ||
425 | interrupts = <3 33>; | ||
426 | clock-frequency = <100000>; | ||
427 | }; | ||
428 | |||
429 | uart0: serial@1180000000800 { | ||
430 | compatible = "cavium,octeon-3860-uart","ns16550"; | ||
431 | reg = <0x11800 0x00000800 0x0 0x400>; | ||
432 | clock-frequency = <0>; | ||
433 | current-speed = <115200>; | ||
434 | reg-shift = <3>; | ||
435 | interrupts = <3 36>; | ||
436 | }; | ||
437 | |||
438 | uart1: serial@1180000000c00 { | ||
439 | compatible = "cavium,octeon-3860-uart","ns16550"; | ||
440 | reg = <0x11800 0x00000c00 0x0 0x400>; | ||
441 | clock-frequency = <0>; | ||
442 | current-speed = <115200>; | ||
443 | reg-shift = <3>; | ||
444 | interrupts = <3 37>; | ||
445 | }; | ||
446 | |||
447 | bootbus: bootbus@1180000000000 { | ||
448 | compatible = "cavium,octeon-3860-bootbus"; | ||
449 | reg = <0x11800 0x00000000 0x0 0x200>; | ||
450 | /* The chip select number and offset */ | ||
451 | #address-cells = <2>; | ||
452 | /* The size of the chip select region */ | ||
453 | #size-cells = <1>; | ||
454 | ranges = <0 0 0 0x1f400000 0xc00000>, | ||
455 | <1 0 0x10000 0x30000000 0>, | ||
456 | <2 0 0x10000 0x40000000 0>, | ||
457 | <3 0 0x10000 0x50000000 0>, | ||
458 | <4 0 0 0x1d020000 0x10000>, | ||
459 | <5 0 0 0x1d040000 0x10000>, | ||
460 | <6 0 0 0x1d050000 0x10000>, | ||
461 | <7 0 0x10000 0x90000000 0>; | ||
462 | |||
463 | cavium,cs-config@0 { | ||
464 | compatible = "cavium,octeon-3860-bootbus-config"; | ||
465 | cavium,cs-index = <0>; | ||
466 | cavium,t-adr = <10>; | ||
467 | cavium,t-ce = <50>; | ||
468 | cavium,t-oe = <50>; | ||
469 | cavium,t-we = <35>; | ||
470 | cavium,t-rd-hld = <25>; | ||
471 | cavium,t-wr-hld = <35>; | ||
472 | cavium,t-pause = <0>; | ||
473 | cavium,t-wait = <300>; | ||
474 | cavium,t-page = <25>; | ||
475 | cavium,t-rd-dly = <0>; | ||
476 | |||
477 | cavium,pages = <0>; | ||
478 | cavium,bus-width = <8>; | ||
479 | }; | ||
480 | cavium,cs-config@4 { | ||
481 | compatible = "cavium,octeon-3860-bootbus-config"; | ||
482 | cavium,cs-index = <4>; | ||
483 | cavium,t-adr = <320>; | ||
484 | cavium,t-ce = <320>; | ||
485 | cavium,t-oe = <320>; | ||
486 | cavium,t-we = <320>; | ||
487 | cavium,t-rd-hld = <320>; | ||
488 | cavium,t-wr-hld = <320>; | ||
489 | cavium,t-pause = <320>; | ||
490 | cavium,t-wait = <320>; | ||
491 | cavium,t-page = <320>; | ||
492 | cavium,t-rd-dly = <0>; | ||
493 | |||
494 | cavium,pages = <0>; | ||
495 | cavium,bus-width = <8>; | ||
496 | }; | ||
497 | cavium,cs-config@5 { | ||
498 | compatible = "cavium,octeon-3860-bootbus-config"; | ||
499 | cavium,cs-index = <5>; | ||
500 | cavium,t-adr = <0>; | ||
501 | cavium,t-ce = <300>; | ||
502 | cavium,t-oe = <125>; | ||
503 | cavium,t-we = <150>; | ||
504 | cavium,t-rd-hld = <100>; | ||
505 | cavium,t-wr-hld = <300>; | ||
506 | cavium,t-pause = <0>; | ||
507 | cavium,t-wait = <300>; | ||
508 | cavium,t-page = <310>; | ||
509 | cavium,t-rd-dly = <0>; | ||
510 | |||
511 | cavium,pages = <0>; | ||
512 | cavium,bus-width = <16>; | ||
513 | }; | ||
514 | cavium,cs-config@6 { | ||
515 | compatible = "cavium,octeon-3860-bootbus-config"; | ||
516 | cavium,cs-index = <6>; | ||
517 | cavium,t-adr = <0>; | ||
518 | cavium,t-ce = <30>; | ||
519 | cavium,t-oe = <125>; | ||
520 | cavium,t-we = <150>; | ||
521 | cavium,t-rd-hld = <100>; | ||
522 | cavium,t-wr-hld = <30>; | ||
523 | cavium,t-pause = <0>; | ||
524 | cavium,t-wait = <30>; | ||
525 | cavium,t-page = <310>; | ||
526 | cavium,t-rd-dly = <0>; | ||
527 | |||
528 | cavium,pages = <0>; | ||
529 | cavium,wait-mode; | ||
530 | cavium,bus-width = <16>; | ||
531 | }; | ||
532 | |||
533 | flash0: nor@0,0 { | ||
534 | compatible = "cfi-flash"; | ||
535 | reg = <0 0 0x800000>; | ||
536 | #address-cells = <1>; | ||
537 | #size-cells = <1>; | ||
538 | |||
539 | partition@0 { | ||
540 | label = "bootloader"; | ||
541 | reg = <0 0x200000>; | ||
542 | read-only; | ||
543 | }; | ||
544 | partition@200000 { | ||
545 | label = "kernel"; | ||
546 | reg = <0x200000 0x200000>; | ||
547 | }; | ||
548 | partition@400000 { | ||
549 | label = "cramfs"; | ||
550 | reg = <0x400000 0x3fe000>; | ||
551 | }; | ||
552 | partition@7fe000 { | ||
553 | label = "environment"; | ||
554 | reg = <0x7fe000 0x2000>; | ||
555 | read-only; | ||
556 | }; | ||
557 | }; | ||
558 | |||
559 | led0: led-display@4,0 { | ||
560 | compatible = "avago,hdsp-253x"; | ||
561 | reg = <4 0x20 0x20>, <4 0 0x20>; | ||
562 | }; | ||
563 | |||
564 | compact-flash@5,0 { | ||
565 | compatible = "cavium,ebt3000-compact-flash"; | ||
566 | reg = <5 0 0x10000>, <6 0 0x10000>; | ||
567 | cavium,bus-width = <16>; | ||
568 | cavium,true-ide; | ||
569 | cavium,dma-engine-handle = <&dma0>; | ||
570 | }; | ||
571 | }; | ||
572 | |||
573 | dma0: dma-engine@1180000000100 { | ||
574 | compatible = "cavium,octeon-5750-bootbus-dma"; | ||
575 | reg = <0x11800 0x00000100 0x0 0x8>; | ||
576 | interrupts = <0 63>; | ||
577 | }; | ||
578 | dma1: dma-engine@1180000000108 { | ||
579 | compatible = "cavium,octeon-5750-bootbus-dma"; | ||
580 | reg = <0x11800 0x00000108 0x0 0x8>; | ||
581 | interrupts = <0 63>; | ||
582 | }; | ||
583 | |||
584 | uctl: uctl@118006f000000 { | ||
585 | compatible = "cavium,octeon-6335-uctl"; | ||
586 | reg = <0x11800 0x6f000000 0x0 0x100>; | ||
587 | ranges; /* Direct mapping */ | ||
588 | #address-cells = <2>; | ||
589 | #size-cells = <2>; | ||
590 | /* 12MHz, 24MHz and 48MHz allowed */ | ||
591 | refclk-frequency = <12000000>; | ||
592 | /* Either "crystal" or "external" */ | ||
593 | refclk-type = "crystal"; | ||
594 | |||
595 | ehci@16f0000000000 { | ||
596 | compatible = "cavium,octeon-6335-ehci","usb-ehci"; | ||
597 | reg = <0x16f00 0x00000000 0x0 0x100>; | ||
598 | interrupts = <3 44>; | ||
599 | big-endian-regs; | ||
600 | }; | ||
601 | ohci@16f0000000400 { | ||
602 | compatible = "cavium,octeon-6335-ohci","usb-ohci"; | ||
603 | reg = <0x16f00 0x00000400 0x0 0x100>; | ||
604 | interrupts = <3 44>; | ||
605 | big-endian-regs; | ||
606 | }; | ||
607 | }; | ||
608 | }; | ||
609 | |||
610 | aliases { | ||
611 | mix0 = &mix0; | ||
612 | pip = &pip; | ||
613 | smi0 = &smi0; | ||
614 | smi1 = &smi1; | ||
615 | smi2 = &smi2; | ||
616 | smi3 = &smi3; | ||
617 | twsi0 = &twsi0; | ||
618 | twsi1 = &twsi1; | ||
619 | uart0 = &uart0; | ||
620 | uart1 = &uart1; | ||
621 | uctl = &uctl; | ||
622 | led0 = &led0; | ||
623 | flash0 = &flash0; | ||
624 | }; | ||
625 | }; | ||
diff --git a/arch/mips/cavium-octeon/serial.c b/arch/mips/cavium-octeon/serial.c index 057f0ae88c9..138b2216b4f 100644 --- a/arch/mips/cavium-octeon/serial.c +++ b/arch/mips/cavium-octeon/serial.c | |||
@@ -43,95 +43,67 @@ void octeon_serial_out(struct uart_port *up, int offset, int value) | |||
43 | cvmx_write_csr((uint64_t)(up->membase + (offset << 3)), (u8)value); | 43 | cvmx_write_csr((uint64_t)(up->membase + (offset << 3)), (u8)value); |
44 | } | 44 | } |
45 | 45 | ||
46 | /* | 46 | static int __devinit octeon_serial_probe(struct platform_device *pdev) |
47 | * Allocated in .bss, so it is all zeroed. | ||
48 | */ | ||
49 | #define OCTEON_MAX_UARTS 3 | ||
50 | static struct plat_serial8250_port octeon_uart8250_data[OCTEON_MAX_UARTS + 1]; | ||
51 | static struct platform_device octeon_uart8250_device = { | ||
52 | .name = "serial8250", | ||
53 | .id = PLAT8250_DEV_PLATFORM, | ||
54 | .dev = { | ||
55 | .platform_data = octeon_uart8250_data, | ||
56 | }, | ||
57 | }; | ||
58 | |||
59 | static void __init octeon_uart_set_common(struct plat_serial8250_port *p) | ||
60 | { | 47 | { |
61 | p->flags = ASYNC_SKIP_TEST | UPF_SHARE_IRQ | UPF_FIXED_TYPE; | 48 | int irq, res; |
62 | p->type = PORT_OCTEON; | 49 | struct resource *res_mem; |
63 | p->iotype = UPIO_MEM; | 50 | struct uart_port port; |
64 | p->regshift = 3; /* I/O addresses are every 8 bytes */ | 51 | |
52 | /* All adaptors have an irq. */ | ||
53 | irq = platform_get_irq(pdev, 0); | ||
54 | if (irq < 0) | ||
55 | return irq; | ||
56 | |||
57 | memset(&port, 0, sizeof(port)); | ||
58 | |||
59 | port.flags = ASYNC_SKIP_TEST | UPF_SHARE_IRQ | UPF_FIXED_TYPE; | ||
60 | port.type = PORT_OCTEON; | ||
61 | port.iotype = UPIO_MEM; | ||
62 | port.regshift = 3; | ||
63 | port.dev = &pdev->dev; | ||
64 | |||
65 | if (octeon_is_simulation()) | 65 | if (octeon_is_simulation()) |
66 | /* Make simulator output fast*/ | 66 | /* Make simulator output fast*/ |
67 | p->uartclk = 115200 * 16; | 67 | port.uartclk = 115200 * 16; |
68 | else | 68 | else |
69 | p->uartclk = octeon_get_io_clock_rate(); | 69 | port.uartclk = octeon_get_io_clock_rate(); |
70 | p->serial_in = octeon_serial_in; | ||
71 | p->serial_out = octeon_serial_out; | ||
72 | } | ||
73 | 70 | ||
74 | static int __init octeon_serial_init(void) | 71 | port.serial_in = octeon_serial_in; |
75 | { | 72 | port.serial_out = octeon_serial_out; |
76 | int enable_uart0; | 73 | port.irq = irq; |
77 | int enable_uart1; | ||
78 | int enable_uart2; | ||
79 | struct plat_serial8250_port *p; | ||
80 | |||
81 | #ifdef CONFIG_CAVIUM_OCTEON_2ND_KERNEL | ||
82 | /* | ||
83 | * If we are configured to run as the second of two kernels, | ||
84 | * disable uart0 and enable uart1. Uart0 is owned by the first | ||
85 | * kernel | ||
86 | */ | ||
87 | enable_uart0 = 0; | ||
88 | enable_uart1 = 1; | ||
89 | #else | ||
90 | /* | ||
91 | * We are configured for the first kernel. We'll enable uart0 | ||
92 | * if the bootloader told us to use 0, otherwise will enable | ||
93 | * uart 1. | ||
94 | */ | ||
95 | enable_uart0 = (octeon_get_boot_uart() == 0); | ||
96 | enable_uart1 = (octeon_get_boot_uart() == 1); | ||
97 | #ifdef CONFIG_KGDB | ||
98 | enable_uart1 = 1; | ||
99 | #endif | ||
100 | #endif | ||
101 | |||
102 | /* Right now CN52XX is the only chip with a third uart */ | ||
103 | enable_uart2 = OCTEON_IS_MODEL(OCTEON_CN52XX); | ||
104 | |||
105 | p = octeon_uart8250_data; | ||
106 | if (enable_uart0) { | ||
107 | /* Add a ttyS device for hardware uart 0 */ | ||
108 | octeon_uart_set_common(p); | ||
109 | p->membase = (void *) CVMX_MIO_UARTX_RBR(0); | ||
110 | p->mapbase = CVMX_MIO_UARTX_RBR(0) & ((1ull << 49) - 1); | ||
111 | p->irq = OCTEON_IRQ_UART0; | ||
112 | p++; | ||
113 | } | ||
114 | 74 | ||
115 | if (enable_uart1) { | 75 | res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
116 | /* Add a ttyS device for hardware uart 1 */ | 76 | if (res_mem == NULL) { |
117 | octeon_uart_set_common(p); | 77 | dev_err(&pdev->dev, "found no memory resource\n"); |
118 | p->membase = (void *) CVMX_MIO_UARTX_RBR(1); | 78 | return -ENXIO; |
119 | p->mapbase = CVMX_MIO_UARTX_RBR(1) & ((1ull << 49) - 1); | ||
120 | p->irq = OCTEON_IRQ_UART1; | ||
121 | p++; | ||
122 | } | ||
123 | if (enable_uart2) { | ||
124 | /* Add a ttyS device for hardware uart 2 */ | ||
125 | octeon_uart_set_common(p); | ||
126 | p->membase = (void *) CVMX_MIO_UART2_RBR; | ||
127 | p->mapbase = CVMX_MIO_UART2_RBR & ((1ull << 49) - 1); | ||
128 | p->irq = OCTEON_IRQ_UART2; | ||
129 | p++; | ||
130 | } | 79 | } |
80 | port.mapbase = res_mem->start; | ||
81 | port.membase = ioremap(res_mem->start, resource_size(res_mem)); | ||
131 | 82 | ||
132 | BUG_ON(p > &octeon_uart8250_data[OCTEON_MAX_UARTS]); | 83 | res = serial8250_register_port(&port); |
133 | 84 | ||
134 | return platform_device_register(&octeon_uart8250_device); | 85 | return res >= 0 ? 0 : res; |
135 | } | 86 | } |
136 | 87 | ||
137 | device_initcall(octeon_serial_init); | 88 | static struct of_device_id octeon_serial_match[] = { |
89 | { | ||
90 | .compatible = "cavium,octeon-3860-uart", | ||
91 | }, | ||
92 | {}, | ||
93 | }; | ||
94 | MODULE_DEVICE_TABLE(of, octeon_serial_match); | ||
95 | |||
96 | static struct platform_driver octeon_serial_driver = { | ||
97 | .probe = octeon_serial_probe, | ||
98 | .driver = { | ||
99 | .owner = THIS_MODULE, | ||
100 | .name = "octeon_serial", | ||
101 | .of_match_table = octeon_serial_match, | ||
102 | }, | ||
103 | }; | ||
104 | |||
105 | static int __init octeon_serial_init(void) | ||
106 | { | ||
107 | return platform_driver_register(&octeon_serial_driver); | ||
108 | } | ||
109 | late_initcall(octeon_serial_init); | ||
diff --git a/arch/mips/cavium-octeon/setup.c b/arch/mips/cavium-octeon/setup.c index 260dc247c05..919b0fb7bb1 100644 --- a/arch/mips/cavium-octeon/setup.c +++ b/arch/mips/cavium-octeon/setup.c | |||
@@ -21,6 +21,8 @@ | |||
21 | #include <linux/platform_device.h> | 21 | #include <linux/platform_device.h> |
22 | #include <linux/serial_core.h> | 22 | #include <linux/serial_core.h> |
23 | #include <linux/serial_8250.h> | 23 | #include <linux/serial_8250.h> |
24 | #include <linux/of_fdt.h> | ||
25 | #include <linux/libfdt.h> | ||
24 | 26 | ||
25 | #include <asm/processor.h> | 27 | #include <asm/processor.h> |
26 | #include <asm/reboot.h> | 28 | #include <asm/reboot.h> |
@@ -775,3 +777,46 @@ void prom_free_prom_memory(void) | |||
775 | } | 777 | } |
776 | #endif | 778 | #endif |
777 | } | 779 | } |
780 | |||
781 | int octeon_prune_device_tree(void); | ||
782 | |||
783 | extern const char __dtb_octeon_3xxx_begin; | ||
784 | extern const char __dtb_octeon_3xxx_end; | ||
785 | extern const char __dtb_octeon_68xx_begin; | ||
786 | extern const char __dtb_octeon_68xx_end; | ||
787 | void __init device_tree_init(void) | ||
788 | { | ||
789 | int dt_size; | ||
790 | struct boot_param_header *fdt; | ||
791 | bool do_prune; | ||
792 | |||
793 | if (octeon_bootinfo->minor_version >= 3 && octeon_bootinfo->fdt_addr) { | ||
794 | fdt = phys_to_virt(octeon_bootinfo->fdt_addr); | ||
795 | if (fdt_check_header(fdt)) | ||
796 | panic("Corrupt Device Tree passed to kernel."); | ||
797 | dt_size = be32_to_cpu(fdt->totalsize); | ||
798 | do_prune = false; | ||
799 | } else if (OCTEON_IS_MODEL(OCTEON_CN68XX)) { | ||
800 | fdt = (struct boot_param_header *)&__dtb_octeon_68xx_begin; | ||
801 | dt_size = &__dtb_octeon_68xx_end - &__dtb_octeon_68xx_begin; | ||
802 | do_prune = true; | ||
803 | } else { | ||
804 | fdt = (struct boot_param_header *)&__dtb_octeon_3xxx_begin; | ||
805 | dt_size = &__dtb_octeon_3xxx_end - &__dtb_octeon_3xxx_begin; | ||
806 | do_prune = true; | ||
807 | } | ||
808 | |||
809 | /* Copy the default tree from init memory. */ | ||
810 | initial_boot_params = early_init_dt_alloc_memory_arch(dt_size, 8); | ||
811 | if (initial_boot_params == NULL) | ||
812 | panic("Could not allocate initial_boot_params\n"); | ||
813 | memcpy(initial_boot_params, fdt, dt_size); | ||
814 | |||
815 | if (do_prune) { | ||
816 | octeon_prune_device_tree(); | ||
817 | pr_info("Using internal Device Tree.\n"); | ||
818 | } else { | ||
819 | pr_info("Using passed Device Tree.\n"); | ||
820 | } | ||
821 | unflatten_device_tree(); | ||
822 | } | ||