diff options
author | Glenn Elliott <gelliott@cs.unc.edu> | 2012-03-04 19:47:13 -0500 |
---|---|---|
committer | Glenn Elliott <gelliott@cs.unc.edu> | 2012-03-04 19:47:13 -0500 |
commit | c71c03bda1e86c9d5198c5d83f712e695c4f2a1e (patch) | |
tree | ecb166cb3e2b7e2adb3b5e292245fefd23381ac8 /arch/powerpc/sysdev/fsl_rio.c | |
parent | ea53c912f8a86a8567697115b6a0d8152beee5c8 (diff) | |
parent | 6a00f206debf8a5c8899055726ad127dbeeed098 (diff) |
Merge branch 'mpi-master' into wip-k-fmlpwip-k-fmlp
Conflicts:
litmus/sched_cedf.c
Diffstat (limited to 'arch/powerpc/sysdev/fsl_rio.c')
-rw-r--r-- | arch/powerpc/sysdev/fsl_rio.c | 380 |
1 files changed, 225 insertions, 155 deletions
diff --git a/arch/powerpc/sysdev/fsl_rio.c b/arch/powerpc/sysdev/fsl_rio.c index 3017532319c8..b3fd081d56f5 100644 --- a/arch/powerpc/sysdev/fsl_rio.c +++ b/arch/powerpc/sysdev/fsl_rio.c | |||
@@ -10,7 +10,7 @@ | |||
10 | * - Added Port-Write message handling | 10 | * - Added Port-Write message handling |
11 | * - Added Machine Check exception handling | 11 | * - Added Machine Check exception handling |
12 | * | 12 | * |
13 | * Copyright (C) 2007, 2008 Freescale Semiconductor, Inc. | 13 | * Copyright (C) 2007, 2008, 2010 Freescale Semiconductor, Inc. |
14 | * Zhang Wei <wei.zhang@freescale.com> | 14 | * Zhang Wei <wei.zhang@freescale.com> |
15 | * | 15 | * |
16 | * Copyright 2005 MontaVista Software, Inc. | 16 | * Copyright 2005 MontaVista Software, Inc. |
@@ -47,14 +47,33 @@ | |||
47 | #define IRQ_RIO_RX(m) (((struct rio_priv *)(m->priv))->rxirq) | 47 | #define IRQ_RIO_RX(m) (((struct rio_priv *)(m->priv))->rxirq) |
48 | #define IRQ_RIO_PW(m) (((struct rio_priv *)(m->priv))->pwirq) | 48 | #define IRQ_RIO_PW(m) (((struct rio_priv *)(m->priv))->pwirq) |
49 | 49 | ||
50 | #define IPWSR_CLEAR 0x98 | ||
51 | #define OMSR_CLEAR 0x1cb3 | ||
52 | #define IMSR_CLEAR 0x491 | ||
53 | #define IDSR_CLEAR 0x91 | ||
54 | #define ODSR_CLEAR 0x1c00 | ||
55 | #define LTLEECSR_ENABLE_ALL 0xFFC000FC | ||
56 | #define ESCSR_CLEAR 0x07120204 | ||
57 | |||
58 | #define RIO_PORT1_EDCSR 0x0640 | ||
59 | #define RIO_PORT2_EDCSR 0x0680 | ||
60 | #define RIO_PORT1_IECSR 0x10130 | ||
61 | #define RIO_PORT2_IECSR 0x101B0 | ||
62 | #define RIO_IM0SR 0x13064 | ||
63 | #define RIO_IM1SR 0x13164 | ||
64 | #define RIO_OM0SR 0x13004 | ||
65 | #define RIO_OM1SR 0x13104 | ||
66 | |||
50 | #define RIO_ATMU_REGS_OFFSET 0x10c00 | 67 | #define RIO_ATMU_REGS_OFFSET 0x10c00 |
51 | #define RIO_P_MSG_REGS_OFFSET 0x11000 | 68 | #define RIO_P_MSG_REGS_OFFSET 0x11000 |
52 | #define RIO_S_MSG_REGS_OFFSET 0x13000 | 69 | #define RIO_S_MSG_REGS_OFFSET 0x13000 |
70 | #define RIO_GCCSR 0x13c | ||
53 | #define RIO_ESCSR 0x158 | 71 | #define RIO_ESCSR 0x158 |
72 | #define RIO_PORT2_ESCSR 0x178 | ||
54 | #define RIO_CCSR 0x15c | 73 | #define RIO_CCSR 0x15c |
55 | #define RIO_LTLEDCSR 0x0608 | 74 | #define RIO_LTLEDCSR 0x0608 |
56 | #define RIO_LTLEDCSR_IER 0x80000000 | 75 | #define RIO_LTLEDCSR_IER 0x80000000 |
57 | #define RIO_LTLEDCSR_PRT 0x01000000 | 76 | #define RIO_LTLEDCSR_PRT 0x01000000 |
58 | #define RIO_LTLEECSR 0x060c | 77 | #define RIO_LTLEECSR 0x060c |
59 | #define RIO_EPWISR 0x10010 | 78 | #define RIO_EPWISR 0x10010 |
60 | #define RIO_ISR_AACR 0x10120 | 79 | #define RIO_ISR_AACR 0x10120 |
@@ -87,6 +106,12 @@ | |||
87 | #define RIO_IPWSR_PWD 0x00000008 | 106 | #define RIO_IPWSR_PWD 0x00000008 |
88 | #define RIO_IPWSR_PWB 0x00000004 | 107 | #define RIO_IPWSR_PWB 0x00000004 |
89 | 108 | ||
109 | /* EPWISR Error match value */ | ||
110 | #define RIO_EPWISR_PINT1 0x80000000 | ||
111 | #define RIO_EPWISR_PINT2 0x40000000 | ||
112 | #define RIO_EPWISR_MU 0x00000002 | ||
113 | #define RIO_EPWISR_PW 0x00000001 | ||
114 | |||
90 | #define RIO_MSG_DESC_SIZE 32 | 115 | #define RIO_MSG_DESC_SIZE 32 |
91 | #define RIO_MSG_BUFFER_SIZE 4096 | 116 | #define RIO_MSG_BUFFER_SIZE 4096 |
92 | #define RIO_MIN_TX_RING_SIZE 2 | 117 | #define RIO_MIN_TX_RING_SIZE 2 |
@@ -117,44 +142,59 @@ struct rio_atmu_regs { | |||
117 | }; | 142 | }; |
118 | 143 | ||
119 | struct rio_msg_regs { | 144 | struct rio_msg_regs { |
120 | u32 omr; | 145 | u32 omr; /* 0xD_3000 - Outbound message 0 mode register */ |
121 | u32 osr; | 146 | u32 osr; /* 0xD_3004 - Outbound message 0 status register */ |
122 | u32 pad1; | 147 | u32 pad1; |
123 | u32 odqdpar; | 148 | u32 odqdpar; /* 0xD_300C - Outbound message 0 descriptor queue |
149 | dequeue pointer address register */ | ||
124 | u32 pad2; | 150 | u32 pad2; |
125 | u32 osar; | 151 | u32 osar; /* 0xD_3014 - Outbound message 0 source address |
126 | u32 odpr; | 152 | register */ |
127 | u32 odatr; | 153 | u32 odpr; /* 0xD_3018 - Outbound message 0 destination port |
128 | u32 odcr; | 154 | register */ |
155 | u32 odatr; /* 0xD_301C - Outbound message 0 destination attributes | ||
156 | Register*/ | ||
157 | u32 odcr; /* 0xD_3020 - Outbound message 0 double-word count | ||
158 | register */ | ||
129 | u32 pad3; | 159 | u32 pad3; |
130 | u32 odqepar; | 160 | u32 odqepar; /* 0xD_3028 - Outbound message 0 descriptor queue |
161 | enqueue pointer address register */ | ||
131 | u32 pad4[13]; | 162 | u32 pad4[13]; |
132 | u32 imr; | 163 | u32 imr; /* 0xD_3060 - Inbound message 0 mode register */ |
133 | u32 isr; | 164 | u32 isr; /* 0xD_3064 - Inbound message 0 status register */ |
134 | u32 pad5; | 165 | u32 pad5; |
135 | u32 ifqdpar; | 166 | u32 ifqdpar; /* 0xD_306C - Inbound message 0 frame queue dequeue |
167 | pointer address register*/ | ||
136 | u32 pad6; | 168 | u32 pad6; |
137 | u32 ifqepar; | 169 | u32 ifqepar; /* 0xD_3074 - Inbound message 0 frame queue enqueue |
170 | pointer address register */ | ||
138 | u32 pad7[226]; | 171 | u32 pad7[226]; |
139 | u32 odmr; | 172 | u32 odmr; /* 0xD_3400 - Outbound doorbell mode register */ |
140 | u32 odsr; | 173 | u32 odsr; /* 0xD_3404 - Outbound doorbell status register */ |
141 | u32 res0[4]; | 174 | u32 res0[4]; |
142 | u32 oddpr; | 175 | u32 oddpr; /* 0xD_3418 - Outbound doorbell destination port |
143 | u32 oddatr; | 176 | register */ |
177 | u32 oddatr; /* 0xD_341c - Outbound doorbell destination attributes | ||
178 | register */ | ||
144 | u32 res1[3]; | 179 | u32 res1[3]; |
145 | u32 odretcr; | 180 | u32 odretcr; /* 0xD_342C - Outbound doorbell retry error threshold |
181 | configuration register */ | ||
146 | u32 res2[12]; | 182 | u32 res2[12]; |
147 | u32 dmr; | 183 | u32 dmr; /* 0xD_3460 - Inbound doorbell mode register */ |
148 | u32 dsr; | 184 | u32 dsr; /* 0xD_3464 - Inbound doorbell status register */ |
149 | u32 pad8; | 185 | u32 pad8; |
150 | u32 dqdpar; | 186 | u32 dqdpar; /* 0xD_346C - Inbound doorbell queue dequeue Pointer |
187 | address register */ | ||
151 | u32 pad9; | 188 | u32 pad9; |
152 | u32 dqepar; | 189 | u32 dqepar; /* 0xD_3474 - Inbound doorbell Queue enqueue pointer |
190 | address register */ | ||
153 | u32 pad10[26]; | 191 | u32 pad10[26]; |
154 | u32 pwmr; | 192 | u32 pwmr; /* 0xD_34E0 - Inbound port-write mode register */ |
155 | u32 pwsr; | 193 | u32 pwsr; /* 0xD_34E4 - Inbound port-write status register */ |
156 | u32 epwqbar; | 194 | u32 epwqbar; /* 0xD_34E8 - Extended Port-Write Queue Base Address |
157 | u32 pwqbar; | 195 | register */ |
196 | u32 pwqbar; /* 0xD_34EC - Inbound port-write queue base address | ||
197 | register */ | ||
158 | }; | 198 | }; |
159 | 199 | ||
160 | struct rio_tx_desc { | 200 | struct rio_tx_desc { |
@@ -241,35 +281,32 @@ struct rio_priv { | |||
241 | static void __iomem *rio_regs_win; | 281 | static void __iomem *rio_regs_win; |
242 | 282 | ||
243 | #ifdef CONFIG_E500 | 283 | #ifdef CONFIG_E500 |
244 | static int (*saved_mcheck_exception)(struct pt_regs *regs); | 284 | int fsl_rio_mcheck_exception(struct pt_regs *regs) |
245 | |||
246 | static int fsl_rio_mcheck_exception(struct pt_regs *regs) | ||
247 | { | 285 | { |
248 | const struct exception_table_entry *entry = NULL; | 286 | const struct exception_table_entry *entry; |
249 | unsigned long reason = mfspr(SPRN_MCSR); | 287 | unsigned long reason; |
250 | 288 | ||
251 | if (reason & MCSR_BUS_RBERR) { | 289 | if (!rio_regs_win) |
252 | reason = in_be32((u32 *)(rio_regs_win + RIO_LTLEDCSR)); | 290 | return 0; |
253 | if (reason & (RIO_LTLEDCSR_IER | RIO_LTLEDCSR_PRT)) { | 291 | |
254 | /* Check if we are prepared to handle this fault */ | 292 | reason = in_be32((u32 *)(rio_regs_win + RIO_LTLEDCSR)); |
255 | entry = search_exception_tables(regs->nip); | 293 | if (reason & (RIO_LTLEDCSR_IER | RIO_LTLEDCSR_PRT)) { |
256 | if (entry) { | 294 | /* Check if we are prepared to handle this fault */ |
257 | pr_debug("RIO: %s - MC Exception handled\n", | 295 | entry = search_exception_tables(regs->nip); |
258 | __func__); | 296 | if (entry) { |
259 | out_be32((u32 *)(rio_regs_win + RIO_LTLEDCSR), | 297 | pr_debug("RIO: %s - MC Exception handled\n", |
260 | 0); | 298 | __func__); |
261 | regs->msr |= MSR_RI; | 299 | out_be32((u32 *)(rio_regs_win + RIO_LTLEDCSR), |
262 | regs->nip = entry->fixup; | 300 | 0); |
263 | return 1; | 301 | regs->msr |= MSR_RI; |
264 | } | 302 | regs->nip = entry->fixup; |
303 | return 1; | ||
265 | } | 304 | } |
266 | } | 305 | } |
267 | 306 | ||
268 | if (saved_mcheck_exception) | 307 | return 0; |
269 | return saved_mcheck_exception(regs); | ||
270 | else | ||
271 | return cur_cpu_spec->machine_check(regs); | ||
272 | } | 308 | } |
309 | EXPORT_SYMBOL_GPL(fsl_rio_mcheck_exception); | ||
273 | #endif | 310 | #endif |
274 | 311 | ||
275 | /** | 312 | /** |
@@ -463,7 +500,7 @@ fsl_rio_config_write(struct rio_mport *mport, int index, u16 destid, | |||
463 | } | 500 | } |
464 | 501 | ||
465 | /** | 502 | /** |
466 | * rio_hw_add_outb_message - Add message to the MPC85xx outbound message queue | 503 | * fsl_add_outb_message - Add message to the MPC85xx outbound message queue |
467 | * @mport: Master port with outbound message queue | 504 | * @mport: Master port with outbound message queue |
468 | * @rdev: Target of outbound message | 505 | * @rdev: Target of outbound message |
469 | * @mbox: Outbound mailbox | 506 | * @mbox: Outbound mailbox |
@@ -473,8 +510,8 @@ fsl_rio_config_write(struct rio_mport *mport, int index, u16 destid, | |||
473 | * Adds the @buffer message to the MPC85xx outbound message queue. Returns | 510 | * Adds the @buffer message to the MPC85xx outbound message queue. Returns |
474 | * %0 on success or %-EINVAL on failure. | 511 | * %0 on success or %-EINVAL on failure. |
475 | */ | 512 | */ |
476 | int | 513 | static int |
477 | rio_hw_add_outb_message(struct rio_mport *mport, struct rio_dev *rdev, int mbox, | 514 | fsl_add_outb_message(struct rio_mport *mport, struct rio_dev *rdev, int mbox, |
478 | void *buffer, size_t len) | 515 | void *buffer, size_t len) |
479 | { | 516 | { |
480 | struct rio_priv *priv = mport->priv; | 517 | struct rio_priv *priv = mport->priv; |
@@ -483,9 +520,8 @@ rio_hw_add_outb_message(struct rio_mport *mport, struct rio_dev *rdev, int mbox, | |||
483 | + priv->msg_tx_ring.tx_slot; | 520 | + priv->msg_tx_ring.tx_slot; |
484 | int ret = 0; | 521 | int ret = 0; |
485 | 522 | ||
486 | pr_debug | 523 | pr_debug("RIO: fsl_add_outb_message(): destid %4.4x mbox %d buffer " \ |
487 | ("RIO: rio_hw_add_outb_message(): destid %4.4x mbox %d buffer %8.8x len %8.8x\n", | 524 | "%8.8x len %8.8x\n", rdev->destid, mbox, (int)buffer, len); |
488 | rdev->destid, mbox, (int)buffer, len); | ||
489 | 525 | ||
490 | if ((len < 8) || (len > RIO_MAX_MSG_SIZE)) { | 526 | if ((len < 8) || (len > RIO_MAX_MSG_SIZE)) { |
491 | ret = -EINVAL; | 527 | ret = -EINVAL; |
@@ -535,8 +571,6 @@ rio_hw_add_outb_message(struct rio_mport *mport, struct rio_dev *rdev, int mbox, | |||
535 | return ret; | 571 | return ret; |
536 | } | 572 | } |
537 | 573 | ||
538 | EXPORT_SYMBOL_GPL(rio_hw_add_outb_message); | ||
539 | |||
540 | /** | 574 | /** |
541 | * fsl_rio_tx_handler - MPC85xx outbound message interrupt handler | 575 | * fsl_rio_tx_handler - MPC85xx outbound message interrupt handler |
542 | * @irq: Linux interrupt number | 576 | * @irq: Linux interrupt number |
@@ -581,7 +615,7 @@ fsl_rio_tx_handler(int irq, void *dev_instance) | |||
581 | } | 615 | } |
582 | 616 | ||
583 | /** | 617 | /** |
584 | * rio_open_outb_mbox - Initialize MPC85xx outbound mailbox | 618 | * fsl_open_outb_mbox - Initialize MPC85xx outbound mailbox |
585 | * @mport: Master port implementing the outbound message unit | 619 | * @mport: Master port implementing the outbound message unit |
586 | * @dev_id: Device specific pointer to pass on event | 620 | * @dev_id: Device specific pointer to pass on event |
587 | * @mbox: Mailbox to open | 621 | * @mbox: Mailbox to open |
@@ -591,7 +625,8 @@ fsl_rio_tx_handler(int irq, void *dev_instance) | |||
591 | * and enables the outbound message unit. Returns %0 on success and | 625 | * and enables the outbound message unit. Returns %0 on success and |
592 | * %-EINVAL or %-ENOMEM on failure. | 626 | * %-EINVAL or %-ENOMEM on failure. |
593 | */ | 627 | */ |
594 | int rio_open_outb_mbox(struct rio_mport *mport, void *dev_id, int mbox, int entries) | 628 | static int |
629 | fsl_open_outb_mbox(struct rio_mport *mport, void *dev_id, int mbox, int entries) | ||
595 | { | 630 | { |
596 | int i, j, rc = 0; | 631 | int i, j, rc = 0; |
597 | struct rio_priv *priv = mport->priv; | 632 | struct rio_priv *priv = mport->priv; |
@@ -687,14 +722,14 @@ int rio_open_outb_mbox(struct rio_mport *mport, void *dev_id, int mbox, int entr | |||
687 | } | 722 | } |
688 | 723 | ||
689 | /** | 724 | /** |
690 | * rio_close_outb_mbox - Shut down MPC85xx outbound mailbox | 725 | * fsl_close_outb_mbox - Shut down MPC85xx outbound mailbox |
691 | * @mport: Master port implementing the outbound message unit | 726 | * @mport: Master port implementing the outbound message unit |
692 | * @mbox: Mailbox to close | 727 | * @mbox: Mailbox to close |
693 | * | 728 | * |
694 | * Disables the outbound message unit, free all buffers, and | 729 | * Disables the outbound message unit, free all buffers, and |
695 | * frees the outbound message interrupt. | 730 | * frees the outbound message interrupt. |
696 | */ | 731 | */ |
697 | void rio_close_outb_mbox(struct rio_mport *mport, int mbox) | 732 | static void fsl_close_outb_mbox(struct rio_mport *mport, int mbox) |
698 | { | 733 | { |
699 | struct rio_priv *priv = mport->priv; | 734 | struct rio_priv *priv = mport->priv; |
700 | /* Disable inbound message unit */ | 735 | /* Disable inbound message unit */ |
@@ -751,7 +786,7 @@ fsl_rio_rx_handler(int irq, void *dev_instance) | |||
751 | } | 786 | } |
752 | 787 | ||
753 | /** | 788 | /** |
754 | * rio_open_inb_mbox - Initialize MPC85xx inbound mailbox | 789 | * fsl_open_inb_mbox - Initialize MPC85xx inbound mailbox |
755 | * @mport: Master port implementing the inbound message unit | 790 | * @mport: Master port implementing the inbound message unit |
756 | * @dev_id: Device specific pointer to pass on event | 791 | * @dev_id: Device specific pointer to pass on event |
757 | * @mbox: Mailbox to open | 792 | * @mbox: Mailbox to open |
@@ -761,7 +796,8 @@ fsl_rio_rx_handler(int irq, void *dev_instance) | |||
761 | * and enables the inbound message unit. Returns %0 on success | 796 | * and enables the inbound message unit. Returns %0 on success |
762 | * and %-EINVAL or %-ENOMEM on failure. | 797 | * and %-EINVAL or %-ENOMEM on failure. |
763 | */ | 798 | */ |
764 | int rio_open_inb_mbox(struct rio_mport *mport, void *dev_id, int mbox, int entries) | 799 | static int |
800 | fsl_open_inb_mbox(struct rio_mport *mport, void *dev_id, int mbox, int entries) | ||
765 | { | 801 | { |
766 | int i, rc = 0; | 802 | int i, rc = 0; |
767 | struct rio_priv *priv = mport->priv; | 803 | struct rio_priv *priv = mport->priv; |
@@ -825,14 +861,14 @@ int rio_open_inb_mbox(struct rio_mport *mport, void *dev_id, int mbox, int entri | |||
825 | } | 861 | } |
826 | 862 | ||
827 | /** | 863 | /** |
828 | * rio_close_inb_mbox - Shut down MPC85xx inbound mailbox | 864 | * fsl_close_inb_mbox - Shut down MPC85xx inbound mailbox |
829 | * @mport: Master port implementing the inbound message unit | 865 | * @mport: Master port implementing the inbound message unit |
830 | * @mbox: Mailbox to close | 866 | * @mbox: Mailbox to close |
831 | * | 867 | * |
832 | * Disables the inbound message unit, free all buffers, and | 868 | * Disables the inbound message unit, free all buffers, and |
833 | * frees the inbound message interrupt. | 869 | * frees the inbound message interrupt. |
834 | */ | 870 | */ |
835 | void rio_close_inb_mbox(struct rio_mport *mport, int mbox) | 871 | static void fsl_close_inb_mbox(struct rio_mport *mport, int mbox) |
836 | { | 872 | { |
837 | struct rio_priv *priv = mport->priv; | 873 | struct rio_priv *priv = mport->priv; |
838 | /* Disable inbound message unit */ | 874 | /* Disable inbound message unit */ |
@@ -847,7 +883,7 @@ void rio_close_inb_mbox(struct rio_mport *mport, int mbox) | |||
847 | } | 883 | } |
848 | 884 | ||
849 | /** | 885 | /** |
850 | * rio_hw_add_inb_buffer - Add buffer to the MPC85xx inbound message queue | 886 | * fsl_add_inb_buffer - Add buffer to the MPC85xx inbound message queue |
851 | * @mport: Master port implementing the inbound message unit | 887 | * @mport: Master port implementing the inbound message unit |
852 | * @mbox: Inbound mailbox number | 888 | * @mbox: Inbound mailbox number |
853 | * @buf: Buffer to add to inbound queue | 889 | * @buf: Buffer to add to inbound queue |
@@ -855,12 +891,12 @@ void rio_close_inb_mbox(struct rio_mport *mport, int mbox) | |||
855 | * Adds the @buf buffer to the MPC85xx inbound message queue. Returns | 891 | * Adds the @buf buffer to the MPC85xx inbound message queue. Returns |
856 | * %0 on success or %-EINVAL on failure. | 892 | * %0 on success or %-EINVAL on failure. |
857 | */ | 893 | */ |
858 | int rio_hw_add_inb_buffer(struct rio_mport *mport, int mbox, void *buf) | 894 | static int fsl_add_inb_buffer(struct rio_mport *mport, int mbox, void *buf) |
859 | { | 895 | { |
860 | int rc = 0; | 896 | int rc = 0; |
861 | struct rio_priv *priv = mport->priv; | 897 | struct rio_priv *priv = mport->priv; |
862 | 898 | ||
863 | pr_debug("RIO: rio_hw_add_inb_buffer(), msg_rx_ring.rx_slot %d\n", | 899 | pr_debug("RIO: fsl_add_inb_buffer(), msg_rx_ring.rx_slot %d\n", |
864 | priv->msg_rx_ring.rx_slot); | 900 | priv->msg_rx_ring.rx_slot); |
865 | 901 | ||
866 | if (priv->msg_rx_ring.virt_buffer[priv->msg_rx_ring.rx_slot]) { | 902 | if (priv->msg_rx_ring.virt_buffer[priv->msg_rx_ring.rx_slot]) { |
@@ -879,17 +915,15 @@ int rio_hw_add_inb_buffer(struct rio_mport *mport, int mbox, void *buf) | |||
879 | return rc; | 915 | return rc; |
880 | } | 916 | } |
881 | 917 | ||
882 | EXPORT_SYMBOL_GPL(rio_hw_add_inb_buffer); | ||
883 | |||
884 | /** | 918 | /** |
885 | * rio_hw_get_inb_message - Fetch inbound message from the MPC85xx message unit | 919 | * fsl_get_inb_message - Fetch inbound message from the MPC85xx message unit |
886 | * @mport: Master port implementing the inbound message unit | 920 | * @mport: Master port implementing the inbound message unit |
887 | * @mbox: Inbound mailbox number | 921 | * @mbox: Inbound mailbox number |
888 | * | 922 | * |
889 | * Gets the next available inbound message from the inbound message queue. | 923 | * Gets the next available inbound message from the inbound message queue. |
890 | * A pointer to the message is returned on success or NULL on failure. | 924 | * A pointer to the message is returned on success or NULL on failure. |
891 | */ | 925 | */ |
892 | void *rio_hw_get_inb_message(struct rio_mport *mport, int mbox) | 926 | static void *fsl_get_inb_message(struct rio_mport *mport, int mbox) |
893 | { | 927 | { |
894 | struct rio_priv *priv = mport->priv; | 928 | struct rio_priv *priv = mport->priv; |
895 | u32 phys_buf, virt_buf; | 929 | u32 phys_buf, virt_buf; |
@@ -926,8 +960,6 @@ void *rio_hw_get_inb_message(struct rio_mport *mport, int mbox) | |||
926 | return buf; | 960 | return buf; |
927 | } | 961 | } |
928 | 962 | ||
929 | EXPORT_SYMBOL_GPL(rio_hw_get_inb_message); | ||
930 | |||
931 | /** | 963 | /** |
932 | * fsl_rio_dbell_handler - MPC85xx doorbell interrupt handler | 964 | * fsl_rio_dbell_handler - MPC85xx doorbell interrupt handler |
933 | * @irq: Linux interrupt number | 965 | * @irq: Linux interrupt number |
@@ -954,7 +986,6 @@ fsl_rio_dbell_handler(int irq, void *dev_instance) | |||
954 | if (dsr & DOORBELL_DSR_QFI) { | 986 | if (dsr & DOORBELL_DSR_QFI) { |
955 | pr_info("RIO: doorbell queue full\n"); | 987 | pr_info("RIO: doorbell queue full\n"); |
956 | out_be32(&priv->msg_regs->dsr, DOORBELL_DSR_QFI); | 988 | out_be32(&priv->msg_regs->dsr, DOORBELL_DSR_QFI); |
957 | goto out; | ||
958 | } | 989 | } |
959 | 990 | ||
960 | /* XXX Need to check/dispatch until queue empty */ | 991 | /* XXX Need to check/dispatch until queue empty */ |
@@ -1051,6 +1082,40 @@ static int fsl_rio_doorbell_init(struct rio_mport *mport) | |||
1051 | return rc; | 1082 | return rc; |
1052 | } | 1083 | } |
1053 | 1084 | ||
1085 | static void port_error_handler(struct rio_mport *port, int offset) | ||
1086 | { | ||
1087 | /*XXX: Error recovery is not implemented, we just clear errors */ | ||
1088 | out_be32((u32 *)(rio_regs_win + RIO_LTLEDCSR), 0); | ||
1089 | |||
1090 | if (offset == 0) { | ||
1091 | out_be32((u32 *)(rio_regs_win + RIO_PORT1_EDCSR), 0); | ||
1092 | out_be32((u32 *)(rio_regs_win + RIO_PORT1_IECSR), 0); | ||
1093 | out_be32((u32 *)(rio_regs_win + RIO_ESCSR), ESCSR_CLEAR); | ||
1094 | } else { | ||
1095 | out_be32((u32 *)(rio_regs_win + RIO_PORT2_EDCSR), 0); | ||
1096 | out_be32((u32 *)(rio_regs_win + RIO_PORT2_IECSR), 0); | ||
1097 | out_be32((u32 *)(rio_regs_win + RIO_PORT2_ESCSR), ESCSR_CLEAR); | ||
1098 | } | ||
1099 | } | ||
1100 | |||
1101 | static void msg_unit_error_handler(struct rio_mport *port) | ||
1102 | { | ||
1103 | struct rio_priv *priv = port->priv; | ||
1104 | |||
1105 | /*XXX: Error recovery is not implemented, we just clear errors */ | ||
1106 | out_be32((u32 *)(rio_regs_win + RIO_LTLEDCSR), 0); | ||
1107 | |||
1108 | out_be32((u32 *)(rio_regs_win + RIO_IM0SR), IMSR_CLEAR); | ||
1109 | out_be32((u32 *)(rio_regs_win + RIO_IM1SR), IMSR_CLEAR); | ||
1110 | out_be32((u32 *)(rio_regs_win + RIO_OM0SR), OMSR_CLEAR); | ||
1111 | out_be32((u32 *)(rio_regs_win + RIO_OM1SR), OMSR_CLEAR); | ||
1112 | |||
1113 | out_be32(&priv->msg_regs->odsr, ODSR_CLEAR); | ||
1114 | out_be32(&priv->msg_regs->dsr, IDSR_CLEAR); | ||
1115 | |||
1116 | out_be32(&priv->msg_regs->pwsr, IPWSR_CLEAR); | ||
1117 | } | ||
1118 | |||
1054 | /** | 1119 | /** |
1055 | * fsl_rio_port_write_handler - MPC85xx port write interrupt handler | 1120 | * fsl_rio_port_write_handler - MPC85xx port write interrupt handler |
1056 | * @irq: Linux interrupt number | 1121 | * @irq: Linux interrupt number |
@@ -1067,18 +1132,12 @@ fsl_rio_port_write_handler(int irq, void *dev_instance) | |||
1067 | struct rio_priv *priv = port->priv; | 1132 | struct rio_priv *priv = port->priv; |
1068 | u32 epwisr, tmp; | 1133 | u32 epwisr, tmp; |
1069 | 1134 | ||
1070 | ipwmr = in_be32(&priv->msg_regs->pwmr); | ||
1071 | ipwsr = in_be32(&priv->msg_regs->pwsr); | ||
1072 | |||
1073 | epwisr = in_be32(priv->regs_win + RIO_EPWISR); | 1135 | epwisr = in_be32(priv->regs_win + RIO_EPWISR); |
1074 | if (epwisr & 0x80000000) { | 1136 | if (!(epwisr & RIO_EPWISR_PW)) |
1075 | tmp = in_be32(priv->regs_win + RIO_LTLEDCSR); | 1137 | goto pw_done; |
1076 | pr_info("RIO_LTLEDCSR = 0x%x\n", tmp); | ||
1077 | out_be32(priv->regs_win + RIO_LTLEDCSR, 0); | ||
1078 | } | ||
1079 | 1138 | ||
1080 | if (!(epwisr & 0x00000001)) | 1139 | ipwmr = in_be32(&priv->msg_regs->pwmr); |
1081 | return IRQ_HANDLED; | 1140 | ipwsr = in_be32(&priv->msg_regs->pwsr); |
1082 | 1141 | ||
1083 | #ifdef DEBUG_PW | 1142 | #ifdef DEBUG_PW |
1084 | pr_debug("PW Int->IPWMR: 0x%08x IPWSR: 0x%08x (", ipwmr, ipwsr); | 1143 | pr_debug("PW Int->IPWMR: 0x%08x IPWSR: 0x%08x (", ipwmr, ipwsr); |
@@ -1094,20 +1153,6 @@ fsl_rio_port_write_handler(int irq, void *dev_instance) | |||
1094 | pr_debug(" PWB"); | 1153 | pr_debug(" PWB"); |
1095 | pr_debug(" )\n"); | 1154 | pr_debug(" )\n"); |
1096 | #endif | 1155 | #endif |
1097 | out_be32(&priv->msg_regs->pwsr, | ||
1098 | ipwsr & (RIO_IPWSR_TE | RIO_IPWSR_QFI | RIO_IPWSR_PWD)); | ||
1099 | |||
1100 | if ((ipwmr & RIO_IPWMR_EIE) && (ipwsr & RIO_IPWSR_TE)) { | ||
1101 | priv->port_write_msg.err_count++; | ||
1102 | pr_info("RIO: Port-Write Transaction Err (%d)\n", | ||
1103 | priv->port_write_msg.err_count); | ||
1104 | } | ||
1105 | if (ipwsr & RIO_IPWSR_PWD) { | ||
1106 | priv->port_write_msg.discard_count++; | ||
1107 | pr_info("RIO: Port Discarded Port-Write Msg(s) (%d)\n", | ||
1108 | priv->port_write_msg.discard_count); | ||
1109 | } | ||
1110 | |||
1111 | /* Schedule deferred processing if PW was received */ | 1156 | /* Schedule deferred processing if PW was received */ |
1112 | if (ipwsr & RIO_IPWSR_QFI) { | 1157 | if (ipwsr & RIO_IPWSR_QFI) { |
1113 | /* Save PW message (if there is room in FIFO), | 1158 | /* Save PW message (if there is room in FIFO), |
@@ -1119,16 +1164,55 @@ fsl_rio_port_write_handler(int irq, void *dev_instance) | |||
1119 | RIO_PW_MSG_SIZE); | 1164 | RIO_PW_MSG_SIZE); |
1120 | } else { | 1165 | } else { |
1121 | priv->port_write_msg.discard_count++; | 1166 | priv->port_write_msg.discard_count++; |
1122 | pr_info("RIO: ISR Discarded Port-Write Msg(s) (%d)\n", | 1167 | pr_debug("RIO: ISR Discarded Port-Write Msg(s) (%d)\n", |
1123 | priv->port_write_msg.discard_count); | 1168 | priv->port_write_msg.discard_count); |
1124 | } | 1169 | } |
1170 | /* Clear interrupt and issue Clear Queue command. This allows | ||
1171 | * another port-write to be received. | ||
1172 | */ | ||
1173 | out_be32(&priv->msg_regs->pwsr, RIO_IPWSR_QFI); | ||
1174 | out_be32(&priv->msg_regs->pwmr, ipwmr | RIO_IPWMR_CQ); | ||
1175 | |||
1125 | schedule_work(&priv->pw_work); | 1176 | schedule_work(&priv->pw_work); |
1126 | } | 1177 | } |
1127 | 1178 | ||
1128 | /* Issue Clear Queue command. This allows another | 1179 | if ((ipwmr & RIO_IPWMR_EIE) && (ipwsr & RIO_IPWSR_TE)) { |
1129 | * port-write to be received. | 1180 | priv->port_write_msg.err_count++; |
1130 | */ | 1181 | pr_debug("RIO: Port-Write Transaction Err (%d)\n", |
1131 | out_be32(&priv->msg_regs->pwmr, ipwmr | RIO_IPWMR_CQ); | 1182 | priv->port_write_msg.err_count); |
1183 | /* Clear Transaction Error: port-write controller should be | ||
1184 | * disabled when clearing this error | ||
1185 | */ | ||
1186 | out_be32(&priv->msg_regs->pwmr, ipwmr & ~RIO_IPWMR_PWE); | ||
1187 | out_be32(&priv->msg_regs->pwsr, RIO_IPWSR_TE); | ||
1188 | out_be32(&priv->msg_regs->pwmr, ipwmr); | ||
1189 | } | ||
1190 | |||
1191 | if (ipwsr & RIO_IPWSR_PWD) { | ||
1192 | priv->port_write_msg.discard_count++; | ||
1193 | pr_debug("RIO: Port Discarded Port-Write Msg(s) (%d)\n", | ||
1194 | priv->port_write_msg.discard_count); | ||
1195 | out_be32(&priv->msg_regs->pwsr, RIO_IPWSR_PWD); | ||
1196 | } | ||
1197 | |||
1198 | pw_done: | ||
1199 | if (epwisr & RIO_EPWISR_PINT1) { | ||
1200 | tmp = in_be32(priv->regs_win + RIO_LTLEDCSR); | ||
1201 | pr_debug("RIO_LTLEDCSR = 0x%x\n", tmp); | ||
1202 | port_error_handler(port, 0); | ||
1203 | } | ||
1204 | |||
1205 | if (epwisr & RIO_EPWISR_PINT2) { | ||
1206 | tmp = in_be32(priv->regs_win + RIO_LTLEDCSR); | ||
1207 | pr_debug("RIO_LTLEDCSR = 0x%x\n", tmp); | ||
1208 | port_error_handler(port, 1); | ||
1209 | } | ||
1210 | |||
1211 | if (epwisr & RIO_EPWISR_MU) { | ||
1212 | tmp = in_be32(priv->regs_win + RIO_LTLEDCSR); | ||
1213 | pr_debug("RIO_LTLEDCSR = 0x%x\n", tmp); | ||
1214 | msg_unit_error_handler(port); | ||
1215 | } | ||
1132 | 1216 | ||
1133 | return IRQ_HANDLED; | 1217 | return IRQ_HANDLED; |
1134 | } | 1218 | } |
@@ -1238,12 +1322,14 @@ static int fsl_rio_port_write_init(struct rio_mport *mport) | |||
1238 | 1322 | ||
1239 | 1323 | ||
1240 | /* Hook up port-write handler */ | 1324 | /* Hook up port-write handler */ |
1241 | rc = request_irq(IRQ_RIO_PW(mport), fsl_rio_port_write_handler, 0, | 1325 | rc = request_irq(IRQ_RIO_PW(mport), fsl_rio_port_write_handler, |
1242 | "port-write", (void *)mport); | 1326 | IRQF_SHARED, "port-write", (void *)mport); |
1243 | if (rc < 0) { | 1327 | if (rc < 0) { |
1244 | pr_err("MPC85xx RIO: unable to request inbound doorbell irq"); | 1328 | pr_err("MPC85xx RIO: unable to request inbound doorbell irq"); |
1245 | goto err_out; | 1329 | goto err_out; |
1246 | } | 1330 | } |
1331 | /* Enable Error Interrupt */ | ||
1332 | out_be32((u32 *)(rio_regs_win + RIO_LTLEECSR), LTLEECSR_ENABLE_ALL); | ||
1247 | 1333 | ||
1248 | INIT_WORK(&priv->pw_work, fsl_pw_dpc); | 1334 | INIT_WORK(&priv->pw_work, fsl_pw_dpc); |
1249 | spin_lock_init(&priv->pw_fifo_lock); | 1335 | spin_lock_init(&priv->pw_fifo_lock); |
@@ -1268,28 +1354,6 @@ err_out: | |||
1268 | return rc; | 1354 | return rc; |
1269 | } | 1355 | } |
1270 | 1356 | ||
1271 | static char *cmdline = NULL; | ||
1272 | |||
1273 | static int fsl_rio_get_hdid(int index) | ||
1274 | { | ||
1275 | /* XXX Need to parse multiple entries in some format */ | ||
1276 | if (!cmdline) | ||
1277 | return -1; | ||
1278 | |||
1279 | return simple_strtol(cmdline, NULL, 0); | ||
1280 | } | ||
1281 | |||
1282 | static int fsl_rio_get_cmdline(char *s) | ||
1283 | { | ||
1284 | if (!s) | ||
1285 | return 0; | ||
1286 | |||
1287 | cmdline = s; | ||
1288 | return 1; | ||
1289 | } | ||
1290 | |||
1291 | __setup("riohdid=", fsl_rio_get_cmdline); | ||
1292 | |||
1293 | static inline void fsl_rio_info(struct device *dev, u32 ccsr) | 1357 | static inline void fsl_rio_info(struct device *dev, u32 ccsr) |
1294 | { | 1358 | { |
1295 | const char *str; | 1359 | const char *str; |
@@ -1406,13 +1470,19 @@ int fsl_rio_setup(struct platform_device *dev) | |||
1406 | ops->cwrite = fsl_rio_config_write; | 1470 | ops->cwrite = fsl_rio_config_write; |
1407 | ops->dsend = fsl_rio_doorbell_send; | 1471 | ops->dsend = fsl_rio_doorbell_send; |
1408 | ops->pwenable = fsl_rio_pw_enable; | 1472 | ops->pwenable = fsl_rio_pw_enable; |
1473 | ops->open_outb_mbox = fsl_open_outb_mbox; | ||
1474 | ops->open_inb_mbox = fsl_open_inb_mbox; | ||
1475 | ops->close_outb_mbox = fsl_close_outb_mbox; | ||
1476 | ops->close_inb_mbox = fsl_close_inb_mbox; | ||
1477 | ops->add_outb_message = fsl_add_outb_message; | ||
1478 | ops->add_inb_buffer = fsl_add_inb_buffer; | ||
1479 | ops->get_inb_message = fsl_get_inb_message; | ||
1409 | 1480 | ||
1410 | port = kzalloc(sizeof(struct rio_mport), GFP_KERNEL); | 1481 | port = kzalloc(sizeof(struct rio_mport), GFP_KERNEL); |
1411 | if (!port) { | 1482 | if (!port) { |
1412 | rc = -ENOMEM; | 1483 | rc = -ENOMEM; |
1413 | goto err_port; | 1484 | goto err_port; |
1414 | } | 1485 | } |
1415 | port->id = 0; | ||
1416 | port->index = 0; | 1486 | port->index = 0; |
1417 | 1487 | ||
1418 | priv = kzalloc(sizeof(struct rio_priv), GFP_KERNEL); | 1488 | priv = kzalloc(sizeof(struct rio_priv), GFP_KERNEL); |
@@ -1428,6 +1498,14 @@ int fsl_rio_setup(struct platform_device *dev) | |||
1428 | port->iores.flags = IORESOURCE_MEM; | 1498 | port->iores.flags = IORESOURCE_MEM; |
1429 | port->iores.name = "rio_io_win"; | 1499 | port->iores.name = "rio_io_win"; |
1430 | 1500 | ||
1501 | if (request_resource(&iomem_resource, &port->iores) < 0) { | ||
1502 | dev_err(&dev->dev, "RIO: Error requesting master port region" | ||
1503 | " 0x%016llx-0x%016llx\n", | ||
1504 | (u64)port->iores.start, (u64)port->iores.end); | ||
1505 | rc = -ENOMEM; | ||
1506 | goto err_res; | ||
1507 | } | ||
1508 | |||
1431 | priv->pwirq = irq_of_parse_and_map(dev->dev.of_node, 0); | 1509 | priv->pwirq = irq_of_parse_and_map(dev->dev.of_node, 0); |
1432 | priv->bellirq = irq_of_parse_and_map(dev->dev.of_node, 2); | 1510 | priv->bellirq = irq_of_parse_and_map(dev->dev.of_node, 2); |
1433 | priv->txirq = irq_of_parse_and_map(dev->dev.of_node, 3); | 1511 | priv->txirq = irq_of_parse_and_map(dev->dev.of_node, 3); |
@@ -1443,10 +1521,8 @@ int fsl_rio_setup(struct platform_device *dev) | |||
1443 | priv->dev = &dev->dev; | 1521 | priv->dev = &dev->dev; |
1444 | 1522 | ||
1445 | port->ops = ops; | 1523 | port->ops = ops; |
1446 | port->host_deviceid = fsl_rio_get_hdid(port->id); | ||
1447 | |||
1448 | port->priv = priv; | 1524 | port->priv = priv; |
1449 | rio_register_mport(port); | 1525 | port->phys_efptr = 0x100; |
1450 | 1526 | ||
1451 | priv->regs_win = ioremap(regs.start, regs.end - regs.start + 1); | 1527 | priv->regs_win = ioremap(regs.start, regs.end - regs.start + 1); |
1452 | rio_regs_win = priv->regs_win; | 1528 | rio_regs_win = priv->regs_win; |
@@ -1493,6 +1569,15 @@ int fsl_rio_setup(struct platform_device *dev) | |||
1493 | dev_info(&dev->dev, "RapidIO Common Transport System size: %d\n", | 1569 | dev_info(&dev->dev, "RapidIO Common Transport System size: %d\n", |
1494 | port->sys_size ? 65536 : 256); | 1570 | port->sys_size ? 65536 : 256); |
1495 | 1571 | ||
1572 | if (rio_register_mport(port)) | ||
1573 | goto err; | ||
1574 | |||
1575 | if (port->host_deviceid >= 0) | ||
1576 | out_be32(priv->regs_win + RIO_GCCSR, RIO_PORT_GEN_HOST | | ||
1577 | RIO_PORT_GEN_MASTER | RIO_PORT_GEN_DISCOVERED); | ||
1578 | else | ||
1579 | out_be32(priv->regs_win + RIO_GCCSR, 0x00000000); | ||
1580 | |||
1496 | priv->atmu_regs = (struct rio_atmu_regs *)(priv->regs_win | 1581 | priv->atmu_regs = (struct rio_atmu_regs *)(priv->regs_win |
1497 | + RIO_ATMU_REGS_OFFSET); | 1582 | + RIO_ATMU_REGS_OFFSET); |
1498 | priv->maint_atmu_regs = priv->atmu_regs + 1; | 1583 | priv->maint_atmu_regs = priv->atmu_regs + 1; |
@@ -1519,16 +1604,10 @@ int fsl_rio_setup(struct platform_device *dev) | |||
1519 | fsl_rio_doorbell_init(port); | 1604 | fsl_rio_doorbell_init(port); |
1520 | fsl_rio_port_write_init(port); | 1605 | fsl_rio_port_write_init(port); |
1521 | 1606 | ||
1522 | #ifdef CONFIG_E500 | ||
1523 | saved_mcheck_exception = ppc_md.machine_check_exception; | ||
1524 | ppc_md.machine_check_exception = fsl_rio_mcheck_exception; | ||
1525 | #endif | ||
1526 | /* Ensure that RFXE is set */ | ||
1527 | mtspr(SPRN_HID1, (mfspr(SPRN_HID1) | 0x20000)); | ||
1528 | |||
1529 | return 0; | 1607 | return 0; |
1530 | err: | 1608 | err: |
1531 | iounmap(priv->regs_win); | 1609 | iounmap(priv->regs_win); |
1610 | err_res: | ||
1532 | kfree(priv); | 1611 | kfree(priv); |
1533 | err_priv: | 1612 | err_priv: |
1534 | kfree(port); | 1613 | kfree(port); |
@@ -1540,21 +1619,12 @@ err_ops: | |||
1540 | 1619 | ||
1541 | /* The probe function for RapidIO peer-to-peer network. | 1620 | /* The probe function for RapidIO peer-to-peer network. |
1542 | */ | 1621 | */ |
1543 | static int __devinit fsl_of_rio_rpn_probe(struct platform_device *dev, | 1622 | static int __devinit fsl_of_rio_rpn_probe(struct platform_device *dev) |
1544 | const struct of_device_id *match) | ||
1545 | { | 1623 | { |
1546 | int rc; | ||
1547 | printk(KERN_INFO "Setting up RapidIO peer-to-peer network %s\n", | 1624 | printk(KERN_INFO "Setting up RapidIO peer-to-peer network %s\n", |
1548 | dev->dev.of_node->full_name); | 1625 | dev->dev.of_node->full_name); |
1549 | 1626 | ||
1550 | rc = fsl_rio_setup(dev); | 1627 | return fsl_rio_setup(dev); |
1551 | if (rc) | ||
1552 | goto out; | ||
1553 | |||
1554 | /* Enumerate all registered ports */ | ||
1555 | rc = rio_init_mports(); | ||
1556 | out: | ||
1557 | return rc; | ||
1558 | }; | 1628 | }; |
1559 | 1629 | ||
1560 | static const struct of_device_id fsl_of_rio_rpn_ids[] = { | 1630 | static const struct of_device_id fsl_of_rio_rpn_ids[] = { |
@@ -1564,7 +1634,7 @@ static const struct of_device_id fsl_of_rio_rpn_ids[] = { | |||
1564 | {}, | 1634 | {}, |
1565 | }; | 1635 | }; |
1566 | 1636 | ||
1567 | static struct of_platform_driver fsl_of_rio_rpn_driver = { | 1637 | static struct platform_driver fsl_of_rio_rpn_driver = { |
1568 | .driver = { | 1638 | .driver = { |
1569 | .name = "fsl-of-rio", | 1639 | .name = "fsl-of-rio", |
1570 | .owner = THIS_MODULE, | 1640 | .owner = THIS_MODULE, |
@@ -1575,7 +1645,7 @@ static struct of_platform_driver fsl_of_rio_rpn_driver = { | |||
1575 | 1645 | ||
1576 | static __init int fsl_of_rio_rpn_init(void) | 1646 | static __init int fsl_of_rio_rpn_init(void) |
1577 | { | 1647 | { |
1578 | return of_register_platform_driver(&fsl_of_rio_rpn_driver); | 1648 | return platform_driver_register(&fsl_of_rio_rpn_driver); |
1579 | } | 1649 | } |
1580 | 1650 | ||
1581 | subsys_initcall(fsl_of_rio_rpn_init); | 1651 | subsys_initcall(fsl_of_rio_rpn_init); |