aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc')
-rw-r--r--arch/powerpc/sysdev/fsl_rio.c74
1 files changed, 70 insertions, 4 deletions
diff --git a/arch/powerpc/sysdev/fsl_rio.c b/arch/powerpc/sysdev/fsl_rio.c
index 73d5f3e142ab..4646cc7aa93a 100644
--- a/arch/powerpc/sysdev/fsl_rio.c
+++ b/arch/powerpc/sysdev/fsl_rio.c
@@ -32,6 +32,8 @@
32#include <linux/kfifo.h> 32#include <linux/kfifo.h>
33 33
34#include <asm/io.h> 34#include <asm/io.h>
35#include <asm/machdep.h>
36#include <asm/uaccess.h>
35 37
36#undef DEBUG_PW /* Port-Write debugging */ 38#undef DEBUG_PW /* Port-Write debugging */
37 39
@@ -47,6 +49,8 @@
47#define RIO_ESCSR 0x158 49#define RIO_ESCSR 0x158
48#define RIO_CCSR 0x15c 50#define RIO_CCSR 0x15c
49#define RIO_LTLEDCSR 0x0608 51#define RIO_LTLEDCSR 0x0608
52#define RIO_LTLEDCSR_IER 0x80000000
53#define RIO_LTLEDCSR_PRT 0x01000000
50#define RIO_LTLEECSR 0x060c 54#define RIO_LTLEECSR 0x060c
51#define RIO_EPWISR 0x10010 55#define RIO_EPWISR 0x10010
52#define RIO_ISR_AACR 0x10120 56#define RIO_ISR_AACR 0x10120
@@ -214,6 +218,54 @@ struct rio_priv {
214 spinlock_t pw_fifo_lock; 218 spinlock_t pw_fifo_lock;
215}; 219};
216 220
221#define __fsl_read_rio_config(x, addr, err, op) \
222 __asm__ __volatile__( \
223 "1: "op" %1,0(%2)\n" \
224 " eieio\n" \
225 "2:\n" \
226 ".section .fixup,\"ax\"\n" \
227 "3: li %1,-1\n" \
228 " li %0,%3\n" \
229 " b 2b\n" \
230 ".section __ex_table,\"a\"\n" \
231 " .align 2\n" \
232 " .long 1b,3b\n" \
233 ".text" \
234 : "=r" (err), "=r" (x) \
235 : "b" (addr), "i" (-EFAULT), "0" (err))
236
237static void __iomem *rio_regs_win;
238
239static int (*saved_mcheck_exception)(struct pt_regs *regs);
240
241static int fsl_rio_mcheck_exception(struct pt_regs *regs)
242{
243 const struct exception_table_entry *entry = NULL;
244 unsigned long reason = (mfspr(SPRN_MCSR) & MCSR_MASK);
245
246 if (reason & MCSR_BUS_RBERR) {
247 reason = in_be32((u32 *)(rio_regs_win + RIO_LTLEDCSR));
248 if (reason & (RIO_LTLEDCSR_IER | RIO_LTLEDCSR_PRT)) {
249 /* Check if we are prepared to handle this fault */
250 entry = search_exception_tables(regs->nip);
251 if (entry) {
252 pr_debug("RIO: %s - MC Exception handled\n",
253 __func__);
254 out_be32((u32 *)(rio_regs_win + RIO_LTLEDCSR),
255 0);
256 regs->msr |= MSR_RI;
257 regs->nip = entry->fixup;
258 return 1;
259 }
260 }
261 }
262
263 if (saved_mcheck_exception)
264 return saved_mcheck_exception(regs);
265 else
266 return cur_cpu_spec->machine_check(regs);
267}
268
217/** 269/**
218 * fsl_rio_doorbell_send - Send a MPC85xx doorbell message 270 * fsl_rio_doorbell_send - Send a MPC85xx doorbell message
219 * @mport: RapidIO master port info 271 * @mport: RapidIO master port info
@@ -314,6 +366,7 @@ fsl_rio_config_read(struct rio_mport *mport, int index, u16 destid,
314{ 366{
315 struct rio_priv *priv = mport->priv; 367 struct rio_priv *priv = mport->priv;
316 u8 *data; 368 u8 *data;
369 u32 rval, err = 0;
317 370
318 pr_debug 371 pr_debug
319 ("fsl_rio_config_read: index %d destid %d hopcount %d offset %8.8x len %d\n", 372 ("fsl_rio_config_read: index %d destid %d hopcount %d offset %8.8x len %d\n",
@@ -324,17 +377,24 @@ fsl_rio_config_read(struct rio_mport *mport, int index, u16 destid,
324 data = (u8 *) priv->maint_win + offset; 377 data = (u8 *) priv->maint_win + offset;
325 switch (len) { 378 switch (len) {
326 case 1: 379 case 1:
327 *val = in_8((u8 *) data); 380 __fsl_read_rio_config(rval, data, err, "lbz");
328 break; 381 break;
329 case 2: 382 case 2:
330 *val = in_be16((u16 *) data); 383 __fsl_read_rio_config(rval, data, err, "lhz");
331 break; 384 break;
332 default: 385 default:
333 *val = in_be32((u32 *) data); 386 __fsl_read_rio_config(rval, data, err, "lwz");
334 break; 387 break;
335 } 388 }
336 389
337 return 0; 390 if (err) {
391 pr_debug("RIO: cfg_read error %d for %x:%x:%x\n",
392 err, destid, hopcount, offset);
393 }
394
395 *val = rval;
396
397 return err;
338} 398}
339 399
340/** 400/**
@@ -1365,6 +1425,7 @@ int fsl_rio_setup(struct of_device *dev)
1365 rio_register_mport(port); 1425 rio_register_mport(port);
1366 1426
1367 priv->regs_win = ioremap(regs.start, regs.end - regs.start + 1); 1427 priv->regs_win = ioremap(regs.start, regs.end - regs.start + 1);
1428 rio_regs_win = priv->regs_win;
1368 1429
1369 /* Probe the master port phy type */ 1430 /* Probe the master port phy type */
1370 ccsr = in_be32(priv->regs_win + RIO_CCSR); 1431 ccsr = in_be32(priv->regs_win + RIO_CCSR);
@@ -1433,6 +1494,11 @@ int fsl_rio_setup(struct of_device *dev)
1433 fsl_rio_doorbell_init(port); 1494 fsl_rio_doorbell_init(port);
1434 fsl_rio_port_write_init(port); 1495 fsl_rio_port_write_init(port);
1435 1496
1497 saved_mcheck_exception = ppc_md.machine_check_exception;
1498 ppc_md.machine_check_exception = fsl_rio_mcheck_exception;
1499 /* Ensure that RFXE is set */
1500 mtspr(SPRN_HID1, (mfspr(SPRN_HID1) | 0x20000));
1501
1436 return 0; 1502 return 0;
1437err: 1503err:
1438 iounmap(priv->regs_win); 1504 iounmap(priv->regs_win);