1 | // SPDX-License-Identifier: GPL-2.0-or-later |
2 | /* |
3 | * Freescale MPC85xx/MPC86xx RapidIO support |
4 | * |
5 | * Copyright 2009 Sysgo AG |
6 | * Thomas Moll <thomas.moll@sysgo.com> |
7 | * - fixed maintenance access routines, check for aligned access |
8 | * |
9 | * Copyright 2009 Integrated Device Technology, Inc. |
10 | * Alex Bounine <alexandre.bounine@idt.com> |
11 | * - Added Port-Write message handling |
12 | * - Added Machine Check exception handling |
13 | * |
14 | * Copyright (C) 2007, 2008, 2010, 2011 Freescale Semiconductor, Inc. |
15 | * Zhang Wei <wei.zhang@freescale.com> |
16 | * |
17 | * Copyright 2005 MontaVista Software, Inc. |
18 | * Matt Porter <mporter@kernel.crashing.org> |
19 | */ |
20 | |
21 | #include <linux/init.h> |
22 | #include <linux/extable.h> |
23 | #include <linux/types.h> |
24 | #include <linux/dma-mapping.h> |
25 | #include <linux/interrupt.h> |
26 | #include <linux/of.h> |
27 | #include <linux/of_address.h> |
28 | #include <linux/of_irq.h> |
29 | #include <linux/platform_device.h> |
30 | #include <linux/delay.h> |
31 | #include <linux/slab.h> |
32 | |
33 | #include <linux/io.h> |
34 | #include <linux/uaccess.h> |
35 | #include <asm/machdep.h> |
36 | #include <asm/rio.h> |
37 | |
38 | #include "fsl_rio.h" |
39 | |
40 | #undef DEBUG_PW /* Port-Write debugging */ |
41 | |
42 | #define RIO_PORT1_EDCSR 0x0640 |
43 | #define RIO_PORT2_EDCSR 0x0680 |
44 | #define RIO_PORT1_IECSR 0x10130 |
45 | #define RIO_PORT2_IECSR 0x101B0 |
46 | |
47 | #define RIO_GCCSR 0x13c |
48 | #define RIO_ESCSR 0x158 |
49 | #define ESCSR_CLEAR 0x07120204 |
50 | #define RIO_PORT2_ESCSR 0x178 |
51 | #define RIO_CCSR 0x15c |
52 | #define RIO_LTLEDCSR_IER 0x80000000 |
53 | #define RIO_LTLEDCSR_PRT 0x01000000 |
54 | #define IECSR_CLEAR 0x80000000 |
55 | #define RIO_ISR_AACR 0x10120 |
56 | #define RIO_ISR_AACR_AA 0x1 /* Accept All ID */ |
57 | |
58 | #define RIWTAR_TRAD_VAL_SHIFT 12 |
59 | #define RIWTAR_TRAD_MASK 0x00FFFFFF |
60 | #define RIWBAR_BADD_VAL_SHIFT 12 |
61 | #define RIWBAR_BADD_MASK 0x003FFFFF |
62 | #define RIWAR_ENABLE 0x80000000 |
63 | #define RIWAR_TGINT_LOCAL 0x00F00000 |
64 | #define RIWAR_RDTYP_NO_SNOOP 0x00040000 |
65 | #define RIWAR_RDTYP_SNOOP 0x00050000 |
66 | #define RIWAR_WRTYP_NO_SNOOP 0x00004000 |
67 | #define RIWAR_WRTYP_SNOOP 0x00005000 |
68 | #define RIWAR_WRTYP_ALLOC 0x00006000 |
69 | #define RIWAR_SIZE_MASK 0x0000003F |
70 | |
71 | static DEFINE_SPINLOCK(fsl_rio_config_lock); |
72 | |
73 | #define ___fsl_read_rio_config(x, addr, err, op, barrier) \ |
74 | __asm__ __volatile__( \ |
75 | "1: "op" %1,0(%2)\n" \ |
76 | " "barrier"\n" \ |
77 | "2:\n" \ |
78 | ".section .fixup,\"ax\"\n" \ |
79 | "3: li %1,-1\n" \ |
80 | " li %0,%3\n" \ |
81 | " b 2b\n" \ |
82 | ".previous\n" \ |
83 | EX_TABLE(1b, 3b) \ |
84 | : "=r" (err), "=r" (x) \ |
85 | : "b" (addr), "i" (-EFAULT), "0" (err)) |
86 | |
87 | #ifdef CONFIG_BOOKE |
88 | #define __fsl_read_rio_config(x, addr, err, op) \ |
89 | ___fsl_read_rio_config(x, addr, err, op, "mbar") |
90 | #else |
91 | #define __fsl_read_rio_config(x, addr, err, op) \ |
92 | ___fsl_read_rio_config(x, addr, err, op, "eieio") |
93 | #endif |
94 | |
95 | void __iomem *rio_regs_win; |
96 | void __iomem *rmu_regs_win; |
97 | resource_size_t rio_law_start; |
98 | |
99 | struct fsl_rio_dbell *dbell; |
100 | struct fsl_rio_pw *pw; |
101 | |
102 | #ifdef CONFIG_PPC_E500 |
103 | int fsl_rio_mcheck_exception(struct pt_regs *regs) |
104 | { |
105 | const struct exception_table_entry *entry; |
106 | unsigned long reason; |
107 | |
108 | if (!rio_regs_win) |
109 | return 0; |
110 | |
111 | reason = in_be32((u32 *)(rio_regs_win + RIO_LTLEDCSR)); |
112 | if (reason & (RIO_LTLEDCSR_IER | RIO_LTLEDCSR_PRT)) { |
113 | /* Check if we are prepared to handle this fault */ |
114 | entry = search_exception_tables(regs->nip); |
115 | if (entry) { |
116 | pr_debug("RIO: %s - MC Exception handled\n" , |
117 | __func__); |
118 | out_be32((u32 *)(rio_regs_win + RIO_LTLEDCSR), |
119 | 0); |
120 | regs_set_recoverable(regs); |
121 | regs_set_return_ip(regs, extable_fixup(entry)); |
122 | return 1; |
123 | } |
124 | } |
125 | |
126 | return 0; |
127 | } |
128 | EXPORT_SYMBOL_GPL(fsl_rio_mcheck_exception); |
129 | #endif |
130 | |
131 | /** |
132 | * fsl_local_config_read - Generate a MPC85xx local config space read |
133 | * @mport: RapidIO master port info |
134 | * @index: ID of RapdiIO interface |
135 | * @offset: Offset into configuration space |
136 | * @len: Length (in bytes) of the maintenance transaction |
137 | * @data: Value to be read into |
138 | * |
139 | * Generates a MPC85xx local configuration space read. Returns %0 on |
140 | * success or %-EINVAL on failure. |
141 | */ |
142 | static int fsl_local_config_read(struct rio_mport *mport, |
143 | int index, u32 offset, int len, u32 *data) |
144 | { |
145 | struct rio_priv *priv = mport->priv; |
146 | pr_debug("fsl_local_config_read: index %d offset %8.8x\n" , index, |
147 | offset); |
148 | *data = in_be32(priv->regs_win + offset); |
149 | |
150 | return 0; |
151 | } |
152 | |
153 | /** |
154 | * fsl_local_config_write - Generate a MPC85xx local config space write |
155 | * @mport: RapidIO master port info |
156 | * @index: ID of RapdiIO interface |
157 | * @offset: Offset into configuration space |
158 | * @len: Length (in bytes) of the maintenance transaction |
159 | * @data: Value to be written |
160 | * |
161 | * Generates a MPC85xx local configuration space write. Returns %0 on |
162 | * success or %-EINVAL on failure. |
163 | */ |
164 | static int fsl_local_config_write(struct rio_mport *mport, |
165 | int index, u32 offset, int len, u32 data) |
166 | { |
167 | struct rio_priv *priv = mport->priv; |
168 | pr_debug |
169 | ("fsl_local_config_write: index %d offset %8.8x data %8.8x\n" , |
170 | index, offset, data); |
171 | out_be32(priv->regs_win + offset, data); |
172 | |
173 | return 0; |
174 | } |
175 | |
176 | /** |
177 | * fsl_rio_config_read - Generate a MPC85xx read maintenance transaction |
178 | * @mport: RapidIO master port info |
179 | * @index: ID of RapdiIO interface |
180 | * @destid: Destination ID of transaction |
181 | * @hopcount: Number of hops to target device |
182 | * @offset: Offset into configuration space |
183 | * @len: Length (in bytes) of the maintenance transaction |
184 | * @val: Location to be read into |
185 | * |
186 | * Generates a MPC85xx read maintenance transaction. Returns %0 on |
187 | * success or %-EINVAL on failure. |
188 | */ |
189 | static int |
190 | fsl_rio_config_read(struct rio_mport *mport, int index, u16 destid, |
191 | u8 hopcount, u32 offset, int len, u32 *val) |
192 | { |
193 | struct rio_priv *priv = mport->priv; |
194 | unsigned long flags; |
195 | u8 *data; |
196 | u32 rval, err = 0; |
197 | |
198 | pr_debug |
199 | ("fsl_rio_config_read:" |
200 | " index %d destid %d hopcount %d offset %8.8x len %d\n" , |
201 | index, destid, hopcount, offset, len); |
202 | |
203 | /* 16MB maintenance window possible */ |
204 | /* allow only aligned access to maintenance registers */ |
205 | if (offset > (0x1000000 - len) || !IS_ALIGNED(offset, len)) |
206 | return -EINVAL; |
207 | |
208 | spin_lock_irqsave(&fsl_rio_config_lock, flags); |
209 | |
210 | out_be32(&priv->maint_atmu_regs->rowtar, |
211 | (destid << 22) | (hopcount << 12) | (offset >> 12)); |
212 | out_be32(&priv->maint_atmu_regs->rowtear, (destid >> 10)); |
213 | |
214 | data = (u8 *) priv->maint_win + (offset & (RIO_MAINT_WIN_SIZE - 1)); |
215 | switch (len) { |
216 | case 1: |
217 | __fsl_read_rio_config(rval, data, err, "lbz" ); |
218 | break; |
219 | case 2: |
220 | __fsl_read_rio_config(rval, data, err, "lhz" ); |
221 | break; |
222 | case 4: |
223 | __fsl_read_rio_config(rval, data, err, "lwz" ); |
224 | break; |
225 | default: |
226 | spin_unlock_irqrestore(lock: &fsl_rio_config_lock, flags); |
227 | return -EINVAL; |
228 | } |
229 | |
230 | if (err) { |
231 | pr_debug("RIO: cfg_read error %d for %x:%x:%x\n" , |
232 | err, destid, hopcount, offset); |
233 | } |
234 | |
235 | spin_unlock_irqrestore(lock: &fsl_rio_config_lock, flags); |
236 | *val = rval; |
237 | |
238 | return err; |
239 | } |
240 | |
241 | /** |
242 | * fsl_rio_config_write - Generate a MPC85xx write maintenance transaction |
243 | * @mport: RapidIO master port info |
244 | * @index: ID of RapdiIO interface |
245 | * @destid: Destination ID of transaction |
246 | * @hopcount: Number of hops to target device |
247 | * @offset: Offset into configuration space |
248 | * @len: Length (in bytes) of the maintenance transaction |
249 | * @val: Value to be written |
250 | * |
251 | * Generates an MPC85xx write maintenance transaction. Returns %0 on |
252 | * success or %-EINVAL on failure. |
253 | */ |
254 | static int |
255 | fsl_rio_config_write(struct rio_mport *mport, int index, u16 destid, |
256 | u8 hopcount, u32 offset, int len, u32 val) |
257 | { |
258 | struct rio_priv *priv = mport->priv; |
259 | unsigned long flags; |
260 | u8 *data; |
261 | int ret = 0; |
262 | |
263 | pr_debug |
264 | ("fsl_rio_config_write:" |
265 | " index %d destid %d hopcount %d offset %8.8x len %d val %8.8x\n" , |
266 | index, destid, hopcount, offset, len, val); |
267 | |
268 | /* 16MB maintenance windows possible */ |
269 | /* allow only aligned access to maintenance registers */ |
270 | if (offset > (0x1000000 - len) || !IS_ALIGNED(offset, len)) |
271 | return -EINVAL; |
272 | |
273 | spin_lock_irqsave(&fsl_rio_config_lock, flags); |
274 | |
275 | out_be32(&priv->maint_atmu_regs->rowtar, |
276 | (destid << 22) | (hopcount << 12) | (offset >> 12)); |
277 | out_be32(&priv->maint_atmu_regs->rowtear, (destid >> 10)); |
278 | |
279 | data = (u8 *) priv->maint_win + (offset & (RIO_MAINT_WIN_SIZE - 1)); |
280 | switch (len) { |
281 | case 1: |
282 | out_8((u8 *) data, val); |
283 | break; |
284 | case 2: |
285 | out_be16((u16 *) data, val); |
286 | break; |
287 | case 4: |
288 | out_be32((u32 *) data, val); |
289 | break; |
290 | default: |
291 | ret = -EINVAL; |
292 | } |
293 | spin_unlock_irqrestore(lock: &fsl_rio_config_lock, flags); |
294 | |
295 | return ret; |
296 | } |
297 | |
298 | static void fsl_rio_inbound_mem_init(struct rio_priv *priv) |
299 | { |
300 | int i; |
301 | |
302 | /* close inbound windows */ |
303 | for (i = 0; i < RIO_INB_ATMU_COUNT; i++) |
304 | out_be32(&priv->inb_atmu_regs[i].riwar, 0); |
305 | } |
306 | |
307 | static int fsl_map_inb_mem(struct rio_mport *mport, dma_addr_t lstart, |
308 | u64 rstart, u64 size, u32 flags) |
309 | { |
310 | struct rio_priv *priv = mport->priv; |
311 | u32 base_size; |
312 | unsigned int base_size_log; |
313 | u64 win_start, win_end; |
314 | u32 riwar; |
315 | int i; |
316 | |
317 | if ((size & (size - 1)) != 0 || size > 0x400000000ULL) |
318 | return -EINVAL; |
319 | |
320 | base_size_log = ilog2(size); |
321 | base_size = 1 << base_size_log; |
322 | |
323 | /* check if addresses are aligned with the window size */ |
324 | if (lstart & (base_size - 1)) |
325 | return -EINVAL; |
326 | if (rstart & (base_size - 1)) |
327 | return -EINVAL; |
328 | |
329 | /* check for conflicting ranges */ |
330 | for (i = 0; i < RIO_INB_ATMU_COUNT; i++) { |
331 | riwar = in_be32(&priv->inb_atmu_regs[i].riwar); |
332 | if ((riwar & RIWAR_ENABLE) == 0) |
333 | continue; |
334 | win_start = ((u64)(in_be32(&priv->inb_atmu_regs[i].riwbar) & RIWBAR_BADD_MASK)) |
335 | << RIWBAR_BADD_VAL_SHIFT; |
336 | win_end = win_start + ((1 << ((riwar & RIWAR_SIZE_MASK) + 1)) - 1); |
337 | if (rstart < win_end && (rstart + size) > win_start) |
338 | return -EINVAL; |
339 | } |
340 | |
341 | /* find unused atmu */ |
342 | for (i = 0; i < RIO_INB_ATMU_COUNT; i++) { |
343 | riwar = in_be32(&priv->inb_atmu_regs[i].riwar); |
344 | if ((riwar & RIWAR_ENABLE) == 0) |
345 | break; |
346 | } |
347 | if (i >= RIO_INB_ATMU_COUNT) |
348 | return -ENOMEM; |
349 | |
350 | out_be32(&priv->inb_atmu_regs[i].riwtar, lstart >> RIWTAR_TRAD_VAL_SHIFT); |
351 | out_be32(&priv->inb_atmu_regs[i].riwbar, rstart >> RIWBAR_BADD_VAL_SHIFT); |
352 | out_be32(&priv->inb_atmu_regs[i].riwar, RIWAR_ENABLE | RIWAR_TGINT_LOCAL | |
353 | RIWAR_RDTYP_SNOOP | RIWAR_WRTYP_SNOOP | (base_size_log - 1)); |
354 | |
355 | return 0; |
356 | } |
357 | |
358 | static void fsl_unmap_inb_mem(struct rio_mport *mport, dma_addr_t lstart) |
359 | { |
360 | u32 win_start_shift, base_start_shift; |
361 | struct rio_priv *priv = mport->priv; |
362 | u32 riwar, riwtar; |
363 | int i; |
364 | |
365 | /* skip default window */ |
366 | base_start_shift = lstart >> RIWTAR_TRAD_VAL_SHIFT; |
367 | for (i = 0; i < RIO_INB_ATMU_COUNT; i++) { |
368 | riwar = in_be32(&priv->inb_atmu_regs[i].riwar); |
369 | if ((riwar & RIWAR_ENABLE) == 0) |
370 | continue; |
371 | |
372 | riwtar = in_be32(&priv->inb_atmu_regs[i].riwtar); |
373 | win_start_shift = riwtar & RIWTAR_TRAD_MASK; |
374 | if (win_start_shift == base_start_shift) { |
375 | out_be32(&priv->inb_atmu_regs[i].riwar, riwar & ~RIWAR_ENABLE); |
376 | return; |
377 | } |
378 | } |
379 | } |
380 | |
381 | void fsl_rio_port_error_handler(int offset) |
382 | { |
383 | /*XXX: Error recovery is not implemented, we just clear errors */ |
384 | out_be32((u32 *)(rio_regs_win + RIO_LTLEDCSR), 0); |
385 | |
386 | if (offset == 0) { |
387 | out_be32((u32 *)(rio_regs_win + RIO_PORT1_EDCSR), 0); |
388 | out_be32((u32 *)(rio_regs_win + RIO_PORT1_IECSR), IECSR_CLEAR); |
389 | out_be32((u32 *)(rio_regs_win + RIO_ESCSR), ESCSR_CLEAR); |
390 | } else { |
391 | out_be32((u32 *)(rio_regs_win + RIO_PORT2_EDCSR), 0); |
392 | out_be32((u32 *)(rio_regs_win + RIO_PORT2_IECSR), IECSR_CLEAR); |
393 | out_be32((u32 *)(rio_regs_win + RIO_PORT2_ESCSR), ESCSR_CLEAR); |
394 | } |
395 | } |
396 | static inline void fsl_rio_info(struct device *dev, u32 ccsr) |
397 | { |
398 | const char *str; |
399 | if (ccsr & 1) { |
400 | /* Serial phy */ |
401 | switch (ccsr >> 30) { |
402 | case 0: |
403 | str = "1" ; |
404 | break; |
405 | case 1: |
406 | str = "4" ; |
407 | break; |
408 | default: |
409 | str = "Unknown" ; |
410 | break; |
411 | } |
412 | dev_info(dev, "Hardware port width: %s\n" , str); |
413 | |
414 | switch ((ccsr >> 27) & 7) { |
415 | case 0: |
416 | str = "Single-lane 0" ; |
417 | break; |
418 | case 1: |
419 | str = "Single-lane 2" ; |
420 | break; |
421 | case 2: |
422 | str = "Four-lane" ; |
423 | break; |
424 | default: |
425 | str = "Unknown" ; |
426 | break; |
427 | } |
428 | dev_info(dev, "Training connection status: %s\n" , str); |
429 | } else { |
430 | /* Parallel phy */ |
431 | if (!(ccsr & 0x80000000)) |
432 | dev_info(dev, "Output port operating in 8-bit mode\n" ); |
433 | if (!(ccsr & 0x08000000)) |
434 | dev_info(dev, "Input port operating in 8-bit mode\n" ); |
435 | } |
436 | } |
437 | |
438 | /** |
439 | * fsl_rio_setup - Setup Freescale PowerPC RapidIO interface |
440 | * @dev: platform_device pointer |
441 | * |
442 | * Initializes MPC85xx RapidIO hardware interface, configures |
443 | * master port with system-specific info, and registers the |
444 | * master port with the RapidIO subsystem. |
445 | */ |
446 | static int fsl_rio_setup(struct platform_device *dev) |
447 | { |
448 | struct rio_ops *ops; |
449 | struct rio_mport *port; |
450 | struct rio_priv *priv; |
451 | int rc = 0; |
452 | const u32 *port_index; |
453 | u32 active_ports = 0; |
454 | struct device_node *np, *rmu_node; |
455 | u32 ccsr; |
456 | u64 range_start; |
457 | u32 i; |
458 | static int tmp; |
459 | struct device_node *rmu_np[MAX_MSG_UNIT_NUM] = {NULL}; |
460 | |
461 | if (!dev->dev.of_node) { |
462 | dev_err(&dev->dev, "Device OF-Node is NULL" ); |
463 | return -ENODEV; |
464 | } |
465 | |
466 | rio_regs_win = of_iomap(node: dev->dev.of_node, index: 0); |
467 | if (!rio_regs_win) { |
468 | dev_err(&dev->dev, "Unable to map rio register window\n" ); |
469 | rc = -ENOMEM; |
470 | goto err_rio_regs; |
471 | } |
472 | |
473 | ops = kzalloc(size: sizeof(struct rio_ops), GFP_KERNEL); |
474 | if (!ops) { |
475 | rc = -ENOMEM; |
476 | goto err_ops; |
477 | } |
478 | ops->lcread = fsl_local_config_read; |
479 | ops->lcwrite = fsl_local_config_write; |
480 | ops->cread = fsl_rio_config_read; |
481 | ops->cwrite = fsl_rio_config_write; |
482 | ops->dsend = fsl_rio_doorbell_send; |
483 | ops->pwenable = fsl_rio_pw_enable; |
484 | ops->open_outb_mbox = fsl_open_outb_mbox; |
485 | ops->open_inb_mbox = fsl_open_inb_mbox; |
486 | ops->close_outb_mbox = fsl_close_outb_mbox; |
487 | ops->close_inb_mbox = fsl_close_inb_mbox; |
488 | ops->add_outb_message = fsl_add_outb_message; |
489 | ops->add_inb_buffer = fsl_add_inb_buffer; |
490 | ops->get_inb_message = fsl_get_inb_message; |
491 | ops->map_inb = fsl_map_inb_mem; |
492 | ops->unmap_inb = fsl_unmap_inb_mem; |
493 | |
494 | rmu_node = of_parse_phandle(np: dev->dev.of_node, phandle_name: "fsl,srio-rmu-handle" , index: 0); |
495 | if (!rmu_node) { |
496 | dev_err(&dev->dev, "No valid fsl,srio-rmu-handle property\n" ); |
497 | rc = -ENOENT; |
498 | goto err_rmu; |
499 | } |
500 | rmu_regs_win = of_iomap(node: rmu_node, index: 0); |
501 | |
502 | of_node_put(node: rmu_node); |
503 | if (!rmu_regs_win) { |
504 | dev_err(&dev->dev, "Unable to map rmu register window\n" ); |
505 | rc = -ENOMEM; |
506 | goto err_rmu; |
507 | } |
508 | for_each_compatible_node(np, NULL, "fsl,srio-msg-unit" ) { |
509 | rmu_np[tmp] = np; |
510 | tmp++; |
511 | } |
512 | |
513 | /*set up doobell node*/ |
514 | np = of_find_compatible_node(NULL, NULL, compat: "fsl,srio-dbell-unit" ); |
515 | if (!np) { |
516 | dev_err(&dev->dev, "No fsl,srio-dbell-unit node\n" ); |
517 | rc = -ENODEV; |
518 | goto err_dbell; |
519 | } |
520 | dbell = kzalloc(size: sizeof(struct fsl_rio_dbell), GFP_KERNEL); |
521 | if (!(dbell)) { |
522 | dev_err(&dev->dev, "Can't alloc memory for 'fsl_rio_dbell'\n" ); |
523 | rc = -ENOMEM; |
524 | goto err_dbell; |
525 | } |
526 | dbell->dev = &dev->dev; |
527 | dbell->bellirq = irq_of_parse_and_map(node: np, index: 1); |
528 | dev_info(&dev->dev, "bellirq: %d\n" , dbell->bellirq); |
529 | |
530 | if (of_property_read_reg(np, idx: 0, addr: &range_start, NULL)) { |
531 | pr_err("%pOF: unable to find 'reg' property\n" , |
532 | np); |
533 | rc = -ENOMEM; |
534 | goto err_pw; |
535 | } |
536 | dbell->dbell_regs = (struct rio_dbell_regs *)(rmu_regs_win + |
537 | (u32)range_start); |
538 | |
539 | /*set up port write node*/ |
540 | np = of_find_compatible_node(NULL, NULL, compat: "fsl,srio-port-write-unit" ); |
541 | if (!np) { |
542 | dev_err(&dev->dev, "No fsl,srio-port-write-unit node\n" ); |
543 | rc = -ENODEV; |
544 | goto err_pw; |
545 | } |
546 | pw = kzalloc(size: sizeof(struct fsl_rio_pw), GFP_KERNEL); |
547 | if (!(pw)) { |
548 | dev_err(&dev->dev, "Can't alloc memory for 'fsl_rio_pw'\n" ); |
549 | rc = -ENOMEM; |
550 | goto err_pw; |
551 | } |
552 | pw->dev = &dev->dev; |
553 | pw->pwirq = irq_of_parse_and_map(node: np, index: 0); |
554 | dev_info(&dev->dev, "pwirq: %d\n" , pw->pwirq); |
555 | if (of_property_read_reg(np, idx: 0, addr: &range_start, NULL)) { |
556 | pr_err("%pOF: unable to find 'reg' property\n" , |
557 | np); |
558 | rc = -ENOMEM; |
559 | goto err; |
560 | } |
561 | pw->pw_regs = (struct rio_pw_regs *)(rmu_regs_win + (u32)range_start); |
562 | |
563 | /*set up ports node*/ |
564 | for_each_child_of_node(dev->dev.of_node, np) { |
565 | struct resource res; |
566 | |
567 | port_index = of_get_property(node: np, name: "cell-index" , NULL); |
568 | if (!port_index) { |
569 | dev_err(&dev->dev, "Can't get %pOF property 'cell-index'\n" , |
570 | np); |
571 | continue; |
572 | } |
573 | |
574 | if (of_range_to_resource(np, index: 0, res: &res)) { |
575 | dev_err(&dev->dev, "Can't get %pOF property 'ranges'\n" , |
576 | np); |
577 | continue; |
578 | } |
579 | |
580 | dev_info(&dev->dev, "%pOF: LAW %pR\n" , |
581 | np, &res); |
582 | |
583 | port = kzalloc(size: sizeof(struct rio_mport), GFP_KERNEL); |
584 | if (!port) |
585 | continue; |
586 | |
587 | rc = rio_mport_initialize(port); |
588 | if (rc) { |
589 | kfree(objp: port); |
590 | continue; |
591 | } |
592 | |
593 | i = *port_index - 1; |
594 | port->index = (unsigned char)i; |
595 | |
596 | priv = kzalloc(size: sizeof(struct rio_priv), GFP_KERNEL); |
597 | if (!priv) { |
598 | dev_err(&dev->dev, "Can't alloc memory for 'priv'\n" ); |
599 | kfree(objp: port); |
600 | continue; |
601 | } |
602 | |
603 | INIT_LIST_HEAD(list: &port->dbells); |
604 | port->iores = res; /* struct copy */ |
605 | port->iores.name = "rio_io_win" ; |
606 | |
607 | if (request_resource(root: &iomem_resource, new: &port->iores) < 0) { |
608 | dev_err(&dev->dev, "RIO: Error requesting master port region" |
609 | " 0x%016llx-0x%016llx\n" , |
610 | (u64)port->iores.start, (u64)port->iores.end); |
611 | kfree(objp: priv); |
612 | kfree(objp: port); |
613 | continue; |
614 | } |
615 | sprintf(buf: port->name, fmt: "RIO mport %d" , i); |
616 | |
617 | priv->dev = &dev->dev; |
618 | port->dev.parent = &dev->dev; |
619 | port->ops = ops; |
620 | port->priv = priv; |
621 | port->phys_efptr = 0x100; |
622 | port->phys_rmap = 1; |
623 | priv->regs_win = rio_regs_win; |
624 | |
625 | ccsr = in_be32(priv->regs_win + RIO_CCSR + i*0x20); |
626 | |
627 | /* Checking the port training status */ |
628 | if (in_be32((priv->regs_win + RIO_ESCSR + i*0x20)) & 1) { |
629 | dev_err(&dev->dev, "Port %d is not ready. " |
630 | "Try to restart connection...\n" , i); |
631 | /* Disable ports */ |
632 | out_be32(priv->regs_win |
633 | + RIO_CCSR + i*0x20, 0); |
634 | /* Set 1x lane */ |
635 | setbits32(priv->regs_win |
636 | + RIO_CCSR + i*0x20, 0x02000000); |
637 | /* Enable ports */ |
638 | setbits32(priv->regs_win |
639 | + RIO_CCSR + i*0x20, 0x00600000); |
640 | msleep(msecs: 100); |
641 | if (in_be32((priv->regs_win |
642 | + RIO_ESCSR + i*0x20)) & 1) { |
643 | dev_err(&dev->dev, |
644 | "Port %d restart failed.\n" , i); |
645 | release_resource(new: &port->iores); |
646 | kfree(objp: priv); |
647 | kfree(objp: port); |
648 | continue; |
649 | } |
650 | dev_info(&dev->dev, "Port %d restart success!\n" , i); |
651 | } |
652 | fsl_rio_info(dev: &dev->dev, ccsr); |
653 | |
654 | port->sys_size = (in_be32((priv->regs_win + RIO_PEF_CAR)) |
655 | & RIO_PEF_CTLS) >> 4; |
656 | dev_info(&dev->dev, "RapidIO Common Transport System size: %d\n" , |
657 | port->sys_size ? 65536 : 256); |
658 | |
659 | if (port->host_deviceid >= 0) |
660 | out_be32(priv->regs_win + RIO_GCCSR, RIO_PORT_GEN_HOST | |
661 | RIO_PORT_GEN_MASTER | RIO_PORT_GEN_DISCOVERED); |
662 | else |
663 | out_be32(priv->regs_win + RIO_GCCSR, |
664 | RIO_PORT_GEN_MASTER); |
665 | |
666 | priv->atmu_regs = (struct rio_atmu_regs *)(priv->regs_win |
667 | + ((i == 0) ? RIO_ATMU_REGS_PORT1_OFFSET : |
668 | RIO_ATMU_REGS_PORT2_OFFSET)); |
669 | |
670 | priv->maint_atmu_regs = priv->atmu_regs + 1; |
671 | priv->inb_atmu_regs = (struct rio_inb_atmu_regs __iomem *) |
672 | (priv->regs_win + |
673 | ((i == 0) ? RIO_INB_ATMU_REGS_PORT1_OFFSET : |
674 | RIO_INB_ATMU_REGS_PORT2_OFFSET)); |
675 | |
676 | /* Set to receive packets with any dest ID */ |
677 | out_be32((priv->regs_win + RIO_ISR_AACR + i*0x80), |
678 | RIO_ISR_AACR_AA); |
679 | |
680 | /* Configure maintenance transaction window */ |
681 | out_be32(&priv->maint_atmu_regs->rowbar, |
682 | port->iores.start >> 12); |
683 | out_be32(&priv->maint_atmu_regs->rowar, |
684 | 0x80077000 | (ilog2(RIO_MAINT_WIN_SIZE) - 1)); |
685 | |
686 | priv->maint_win = ioremap(offset: port->iores.start, |
687 | RIO_MAINT_WIN_SIZE); |
688 | |
689 | rio_law_start = range_start; |
690 | |
691 | fsl_rio_setup_rmu(mport: port, node: rmu_np[i]); |
692 | fsl_rio_inbound_mem_init(priv); |
693 | |
694 | dbell->mport[i] = port; |
695 | pw->mport[i] = port; |
696 | |
697 | if (rio_register_mport(port)) { |
698 | release_resource(new: &port->iores); |
699 | kfree(objp: priv); |
700 | kfree(objp: port); |
701 | continue; |
702 | } |
703 | active_ports++; |
704 | } |
705 | |
706 | if (!active_ports) { |
707 | rc = -ENOLINK; |
708 | goto err; |
709 | } |
710 | |
711 | fsl_rio_doorbell_init(dbell); |
712 | fsl_rio_port_write_init(pw); |
713 | |
714 | return 0; |
715 | err: |
716 | kfree(objp: pw); |
717 | pw = NULL; |
718 | err_pw: |
719 | kfree(objp: dbell); |
720 | dbell = NULL; |
721 | err_dbell: |
722 | iounmap(addr: rmu_regs_win); |
723 | rmu_regs_win = NULL; |
724 | err_rmu: |
725 | kfree(objp: ops); |
726 | err_ops: |
727 | iounmap(addr: rio_regs_win); |
728 | rio_regs_win = NULL; |
729 | err_rio_regs: |
730 | return rc; |
731 | } |
732 | |
733 | /* The probe function for RapidIO peer-to-peer network. |
734 | */ |
735 | static int fsl_of_rio_rpn_probe(struct platform_device *dev) |
736 | { |
737 | printk(KERN_INFO "Setting up RapidIO peer-to-peer network %pOF\n" , |
738 | dev->dev.of_node); |
739 | |
740 | return fsl_rio_setup(dev); |
741 | }; |
742 | |
743 | static const struct of_device_id fsl_of_rio_rpn_ids[] = { |
744 | { |
745 | .compatible = "fsl,srio" , |
746 | }, |
747 | {}, |
748 | }; |
749 | |
750 | static struct platform_driver fsl_of_rio_rpn_driver = { |
751 | .driver = { |
752 | .name = "fsl-of-rio" , |
753 | .of_match_table = fsl_of_rio_rpn_ids, |
754 | }, |
755 | .probe = fsl_of_rio_rpn_probe, |
756 | }; |
757 | |
758 | static __init int fsl_of_rio_rpn_init(void) |
759 | { |
760 | return platform_driver_register(&fsl_of_rio_rpn_driver); |
761 | } |
762 | |
763 | subsys_initcall(fsl_of_rio_rpn_init); |
764 | |