aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc
diff options
context:
space:
mode:
authorKumar Gala <galak@kernel.crashing.org>2008-01-23 07:12:06 -0500
committerKumar Gala <galak@kernel.crashing.org>2008-01-23 20:35:15 -0500
commitde3c8d41828553fa4cbba0399826e20a02670663 (patch)
tree8228ee8626f9b991f68f00c95635fbb8922476c6 /arch/powerpc
parent5febf1cd79425d3c65d9a66a2299f0d06dc4b1eb (diff)
[POWERPC] Move RapidIO support code from arch/ppc
Do just enough to move the RapidIO support code for 85xx over from arch/ppc into arch/powerpc and make it still build. Signed-off-by: Kumar Gala <galak@kernel.crashing.org>
Diffstat (limited to 'arch/powerpc')
-rw-r--r--arch/powerpc/kernel/Makefile1
-rw-r--r--arch/powerpc/kernel/rio.c52
-rw-r--r--arch/powerpc/sysdev/Makefile1
-rw-r--r--arch/powerpc/sysdev/fsl_rio.c932
-rw-r--r--arch/powerpc/sysdev/fsl_rio.h20
5 files changed, 1006 insertions, 0 deletions
diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile
index d9b377070caa..58dbfeff9b4d 100644
--- a/arch/powerpc/kernel/Makefile
+++ b/arch/powerpc/kernel/Makefile
@@ -70,6 +70,7 @@ pci64-$(CONFIG_PPC64) += pci_dn.o isa-bridge.o
70obj-$(CONFIG_PCI) += pci_$(CONFIG_WORD_SIZE).o $(pci64-y) \ 70obj-$(CONFIG_PCI) += pci_$(CONFIG_WORD_SIZE).o $(pci64-y) \
71 pci-common.o 71 pci-common.o
72obj-$(CONFIG_PCI_MSI) += msi.o 72obj-$(CONFIG_PCI_MSI) += msi.o
73obj-$(CONFIG_RAPIDIO) += rio.o
73obj-$(CONFIG_KEXEC) += machine_kexec.o crash.o \ 74obj-$(CONFIG_KEXEC) += machine_kexec.o crash.o \
74 machine_kexec_$(CONFIG_WORD_SIZE).o 75 machine_kexec_$(CONFIG_WORD_SIZE).o
75obj-$(CONFIG_AUDIT) += audit.o 76obj-$(CONFIG_AUDIT) += audit.o
diff --git a/arch/powerpc/kernel/rio.c b/arch/powerpc/kernel/rio.c
new file mode 100644
index 000000000000..29487fedfc76
--- /dev/null
+++ b/arch/powerpc/kernel/rio.c
@@ -0,0 +1,52 @@
1/*
2 * RapidIO PPC32 support
3 *
4 * Copyright 2005 MontaVista Software, Inc.
5 * Matt Porter <mporter@kernel.crashing.org>
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version.
11 */
12
13#include <linux/init.h>
14#include <linux/kernel.h>
15#include <linux/rio.h>
16
17#include <asm/rio.h>
18
19/**
20 * platform_rio_init - Do platform specific RIO init
21 *
22 * Any platform specific initialization of RapdIO
23 * hardware is done here as well as registration
24 * of any active master ports in the system.
25 */
26void __attribute__ ((weak))
27 platform_rio_init(void)
28{
29 printk(KERN_WARNING "RIO: No platform_rio_init() present\n");
30}
31
32/**
33 * ppc_rio_init - Do PPC32 RIO init
34 *
35 * Calls platform-specific RIO init code and then calls
36 * rio_init_mports() to initialize any master ports that
37 * have been registered with the RIO subsystem.
38 */
39static int __init ppc_rio_init(void)
40{
41 printk(KERN_INFO "RIO: RapidIO init\n");
42
43 /* Platform specific initialization */
44 platform_rio_init();
45
46 /* Enumerate all registered ports */
47 rio_init_mports();
48
49 return 0;
50}
51
52subsys_initcall(ppc_rio_init);
diff --git a/arch/powerpc/sysdev/Makefile b/arch/powerpc/sysdev/Makefile
index 66fe39cff36a..f17e7b885f60 100644
--- a/arch/powerpc/sysdev/Makefile
+++ b/arch/powerpc/sysdev/Makefile
@@ -12,6 +12,7 @@ obj-$(CONFIG_U3_DART) += dart_iommu.o
12obj-$(CONFIG_MMIO_NVRAM) += mmio_nvram.o 12obj-$(CONFIG_MMIO_NVRAM) += mmio_nvram.o
13obj-$(CONFIG_FSL_SOC) += fsl_soc.o 13obj-$(CONFIG_FSL_SOC) += fsl_soc.o
14obj-$(CONFIG_FSL_PCI) += fsl_pci.o 14obj-$(CONFIG_FSL_PCI) += fsl_pci.o
15obj-$(CONFIG_RAPIDIO) += fsl_rio.o
15obj-$(CONFIG_TSI108_BRIDGE) += tsi108_pci.o tsi108_dev.o 16obj-$(CONFIG_TSI108_BRIDGE) += tsi108_pci.o tsi108_dev.o
16obj-$(CONFIG_QUICC_ENGINE) += qe_lib/ 17obj-$(CONFIG_QUICC_ENGINE) += qe_lib/
17obj-$(CONFIG_PPC_BESTCOMM) += bestcomm/ 18obj-$(CONFIG_PPC_BESTCOMM) += bestcomm/
diff --git a/arch/powerpc/sysdev/fsl_rio.c b/arch/powerpc/sysdev/fsl_rio.c
new file mode 100644
index 000000000000..af2425e4655f
--- /dev/null
+++ b/arch/powerpc/sysdev/fsl_rio.c
@@ -0,0 +1,932 @@
1/*
2 * MPC85xx RapidIO support
3 *
4 * Copyright 2005 MontaVista Software, Inc.
5 * Matt Porter <mporter@kernel.crashing.org>
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version.
11 */
12
13#include <linux/init.h>
14#include <linux/module.h>
15#include <linux/types.h>
16#include <linux/dma-mapping.h>
17#include <linux/interrupt.h>
18#include <linux/rio.h>
19#include <linux/rio_drv.h>
20
21#include <asm/io.h>
22
23#define RIO_REGS_BASE (CCSRBAR + 0xc0000)
24#define RIO_ATMU_REGS_OFFSET 0x10c00
25#define RIO_MSG_REGS_OFFSET 0x11000
26#define RIO_MAINT_WIN_SIZE 0x400000
27#define RIO_DBELL_WIN_SIZE 0x1000
28
29#define RIO_MSG_OMR_MUI 0x00000002
30#define RIO_MSG_OSR_TE 0x00000080
31#define RIO_MSG_OSR_QOI 0x00000020
32#define RIO_MSG_OSR_QFI 0x00000010
33#define RIO_MSG_OSR_MUB 0x00000004
34#define RIO_MSG_OSR_EOMI 0x00000002
35#define RIO_MSG_OSR_QEI 0x00000001
36
37#define RIO_MSG_IMR_MI 0x00000002
38#define RIO_MSG_ISR_TE 0x00000080
39#define RIO_MSG_ISR_QFI 0x00000010
40#define RIO_MSG_ISR_DIQI 0x00000001
41
42#define RIO_MSG_DESC_SIZE 32
43#define RIO_MSG_BUFFER_SIZE 4096
44#define RIO_MIN_TX_RING_SIZE 2
45#define RIO_MAX_TX_RING_SIZE 2048
46#define RIO_MIN_RX_RING_SIZE 2
47#define RIO_MAX_RX_RING_SIZE 2048
48
49#define DOORBELL_DMR_DI 0x00000002
50#define DOORBELL_DSR_TE 0x00000080
51#define DOORBELL_DSR_QFI 0x00000010
52#define DOORBELL_DSR_DIQI 0x00000001
53#define DOORBELL_TID_OFFSET 0x03
54#define DOORBELL_SID_OFFSET 0x05
55#define DOORBELL_INFO_OFFSET 0x06
56
57#define DOORBELL_MESSAGE_SIZE 0x08
58#define DBELL_SID(x) (*(u8 *)(x + DOORBELL_SID_OFFSET))
59#define DBELL_TID(x) (*(u8 *)(x + DOORBELL_TID_OFFSET))
60#define DBELL_INF(x) (*(u16 *)(x + DOORBELL_INFO_OFFSET))
61
62struct rio_atmu_regs {
63 u32 rowtar;
64 u32 pad1;
65 u32 rowbar;
66 u32 pad2;
67 u32 rowar;
68 u32 pad3[3];
69};
70
71struct rio_msg_regs {
72 u32 omr;
73 u32 osr;
74 u32 pad1;
75 u32 odqdpar;
76 u32 pad2;
77 u32 osar;
78 u32 odpr;
79 u32 odatr;
80 u32 odcr;
81 u32 pad3;
82 u32 odqepar;
83 u32 pad4[13];
84 u32 imr;
85 u32 isr;
86 u32 pad5;
87 u32 ifqdpar;
88 u32 pad6;
89 u32 ifqepar;
90 u32 pad7[250];
91 u32 dmr;
92 u32 dsr;
93 u32 pad8;
94 u32 dqdpar;
95 u32 pad9;
96 u32 dqepar;
97 u32 pad10[26];
98 u32 pwmr;
99 u32 pwsr;
100 u32 pad11;
101 u32 pwqbar;
102};
103
104struct rio_tx_desc {
105 u32 res1;
106 u32 saddr;
107 u32 dport;
108 u32 dattr;
109 u32 res2;
110 u32 res3;
111 u32 dwcnt;
112 u32 res4;
113};
114
115static u32 regs_win;
116static struct rio_atmu_regs *atmu_regs;
117static struct rio_atmu_regs *maint_atmu_regs;
118static struct rio_atmu_regs *dbell_atmu_regs;
119static u32 dbell_win;
120static u32 maint_win;
121static struct rio_msg_regs *msg_regs;
122
123static struct rio_dbell_ring {
124 void *virt;
125 dma_addr_t phys;
126} dbell_ring;
127
128static struct rio_msg_tx_ring {
129 void *virt;
130 dma_addr_t phys;
131 void *virt_buffer[RIO_MAX_TX_RING_SIZE];
132 dma_addr_t phys_buffer[RIO_MAX_TX_RING_SIZE];
133 int tx_slot;
134 int size;
135 void *dev_id;
136} msg_tx_ring;
137
138static struct rio_msg_rx_ring {
139 void *virt;
140 dma_addr_t phys;
141 void *virt_buffer[RIO_MAX_RX_RING_SIZE];
142 int rx_slot;
143 int size;
144 void *dev_id;
145} msg_rx_ring;
146
147/**
148 * mpc85xx_rio_doorbell_send - Send a MPC85xx doorbell message
149 * @index: ID of RapidIO interface
150 * @destid: Destination ID of target device
151 * @data: 16-bit info field of RapidIO doorbell message
152 *
153 * Sends a MPC85xx doorbell message. Returns %0 on success or
154 * %-EINVAL on failure.
155 */
156static int mpc85xx_rio_doorbell_send(int index, u16 destid, u16 data)
157{
158 pr_debug("mpc85xx_doorbell_send: index %d destid %4.4x data %4.4x\n",
159 index, destid, data);
160 out_be32((void *)&dbell_atmu_regs->rowtar, destid << 22);
161 out_be16((void *)(dbell_win), data);
162
163 return 0;
164}
165
166/**
167 * mpc85xx_local_config_read - Generate a MPC85xx local config space read
168 * @index: ID of RapdiIO interface
169 * @offset: Offset into configuration space
170 * @len: Length (in bytes) of the maintenance transaction
171 * @data: Value to be read into
172 *
173 * Generates a MPC85xx local configuration space read. Returns %0 on
174 * success or %-EINVAL on failure.
175 */
176static int mpc85xx_local_config_read(int index, u32 offset, int len, u32 * data)
177{
178 pr_debug("mpc85xx_local_config_read: index %d offset %8.8x\n", index,
179 offset);
180 *data = in_be32((void *)(regs_win + offset));
181
182 return 0;
183}
184
185/**
186 * mpc85xx_local_config_write - Generate a MPC85xx local config space write
187 * @index: ID of RapdiIO interface
188 * @offset: Offset into configuration space
189 * @len: Length (in bytes) of the maintenance transaction
190 * @data: Value to be written
191 *
192 * Generates a MPC85xx local configuration space write. Returns %0 on
193 * success or %-EINVAL on failure.
194 */
195static int mpc85xx_local_config_write(int index, u32 offset, int len, u32 data)
196{
197 pr_debug
198 ("mpc85xx_local_config_write: index %d offset %8.8x data %8.8x\n",
199 index, offset, data);
200 out_be32((void *)(regs_win + offset), data);
201
202 return 0;
203}
204
205/**
206 * mpc85xx_rio_config_read - Generate a MPC85xx read maintenance transaction
207 * @index: ID of RapdiIO interface
208 * @destid: Destination ID of transaction
209 * @hopcount: Number of hops to target device
210 * @offset: Offset into configuration space
211 * @len: Length (in bytes) of the maintenance transaction
212 * @val: Location to be read into
213 *
214 * Generates a MPC85xx read maintenance transaction. Returns %0 on
215 * success or %-EINVAL on failure.
216 */
217static int
218mpc85xx_rio_config_read(int index, u16 destid, u8 hopcount, u32 offset, int len,
219 u32 * val)
220{
221 u8 *data;
222
223 pr_debug
224 ("mpc85xx_rio_config_read: index %d destid %d hopcount %d offset %8.8x len %d\n",
225 index, destid, hopcount, offset, len);
226 out_be32((void *)&maint_atmu_regs->rowtar,
227 (destid << 22) | (hopcount << 12) | ((offset & ~0x3) >> 9));
228
229 data = (u8 *) maint_win + offset;
230 switch (len) {
231 case 1:
232 *val = in_8((u8 *) data);
233 break;
234 case 2:
235 *val = in_be16((u16 *) data);
236 break;
237 default:
238 *val = in_be32((u32 *) data);
239 break;
240 }
241
242 return 0;
243}
244
245/**
246 * mpc85xx_rio_config_write - Generate a MPC85xx write maintenance transaction
247 * @index: ID of RapdiIO interface
248 * @destid: Destination ID of transaction
249 * @hopcount: Number of hops to target device
250 * @offset: Offset into configuration space
251 * @len: Length (in bytes) of the maintenance transaction
252 * @val: Value to be written
253 *
254 * Generates an MPC85xx write maintenance transaction. Returns %0 on
255 * success or %-EINVAL on failure.
256 */
257static int
258mpc85xx_rio_config_write(int index, u16 destid, u8 hopcount, u32 offset,
259 int len, u32 val)
260{
261 u8 *data;
262 pr_debug
263 ("mpc85xx_rio_config_write: index %d destid %d hopcount %d offset %8.8x len %d val %8.8x\n",
264 index, destid, hopcount, offset, len, val);
265 out_be32((void *)&maint_atmu_regs->rowtar,
266 (destid << 22) | (hopcount << 12) | ((offset & ~0x3) >> 9));
267
268 data = (u8 *) maint_win + offset;
269 switch (len) {
270 case 1:
271 out_8((u8 *) data, val);
272 break;
273 case 2:
274 out_be16((u16 *) data, val);
275 break;
276 default:
277 out_be32((u32 *) data, val);
278 break;
279 }
280
281 return 0;
282}
283
284/**
285 * rio_hw_add_outb_message - Add message to the MPC85xx outbound message queue
286 * @mport: Master port with outbound message queue
287 * @rdev: Target of outbound message
288 * @mbox: Outbound mailbox
289 * @buffer: Message to add to outbound queue
290 * @len: Length of message
291 *
292 * Adds the @buffer message to the MPC85xx outbound message queue. Returns
293 * %0 on success or %-EINVAL on failure.
294 */
295int
296rio_hw_add_outb_message(struct rio_mport *mport, struct rio_dev *rdev, int mbox,
297 void *buffer, size_t len)
298{
299 u32 omr;
300 struct rio_tx_desc *desc =
301 (struct rio_tx_desc *)msg_tx_ring.virt + msg_tx_ring.tx_slot;
302 int ret = 0;
303
304 pr_debug
305 ("RIO: rio_hw_add_outb_message(): destid %4.4x mbox %d buffer %8.8x len %8.8x\n",
306 rdev->destid, mbox, (int)buffer, len);
307
308 if ((len < 8) || (len > RIO_MAX_MSG_SIZE)) {
309 ret = -EINVAL;
310 goto out;
311 }
312
313 /* Copy and clear rest of buffer */
314 memcpy(msg_tx_ring.virt_buffer[msg_tx_ring.tx_slot], buffer, len);
315 if (len < (RIO_MAX_MSG_SIZE - 4))
316 memset((void *)((u32) msg_tx_ring.
317 virt_buffer[msg_tx_ring.tx_slot] + len), 0,
318 RIO_MAX_MSG_SIZE - len);
319
320 /* Set mbox field for message */
321 desc->dport = mbox & 0x3;
322
323 /* Enable EOMI interrupt, set priority, and set destid */
324 desc->dattr = 0x28000000 | (rdev->destid << 2);
325
326 /* Set transfer size aligned to next power of 2 (in double words) */
327 desc->dwcnt = is_power_of_2(len) ? len : 1 << get_bitmask_order(len);
328
329 /* Set snooping and source buffer address */
330 desc->saddr = 0x00000004 | msg_tx_ring.phys_buffer[msg_tx_ring.tx_slot];
331
332 /* Increment enqueue pointer */
333 omr = in_be32((void *)&msg_regs->omr);
334 out_be32((void *)&msg_regs->omr, omr | RIO_MSG_OMR_MUI);
335
336 /* Go to next descriptor */
337 if (++msg_tx_ring.tx_slot == msg_tx_ring.size)
338 msg_tx_ring.tx_slot = 0;
339
340 out:
341 return ret;
342}
343
344EXPORT_SYMBOL_GPL(rio_hw_add_outb_message);
345
346/**
347 * mpc85xx_rio_tx_handler - MPC85xx outbound message interrupt handler
348 * @irq: Linux interrupt number
349 * @dev_instance: Pointer to interrupt-specific data
350 *
351 * Handles outbound message interrupts. Executes a register outbound
352 * mailbox event handler and acks the interrupt occurrence.
353 */
354static irqreturn_t
355mpc85xx_rio_tx_handler(int irq, void *dev_instance)
356{
357 int osr;
358 struct rio_mport *port = (struct rio_mport *)dev_instance;
359
360 osr = in_be32((void *)&msg_regs->osr);
361
362 if (osr & RIO_MSG_OSR_TE) {
363 pr_info("RIO: outbound message transmission error\n");
364 out_be32((void *)&msg_regs->osr, RIO_MSG_OSR_TE);
365 goto out;
366 }
367
368 if (osr & RIO_MSG_OSR_QOI) {
369 pr_info("RIO: outbound message queue overflow\n");
370 out_be32((void *)&msg_regs->osr, RIO_MSG_OSR_QOI);
371 goto out;
372 }
373
374 if (osr & RIO_MSG_OSR_EOMI) {
375 u32 dqp = in_be32((void *)&msg_regs->odqdpar);
376 int slot = (dqp - msg_tx_ring.phys) >> 5;
377 port->outb_msg[0].mcback(port, msg_tx_ring.dev_id, -1, slot);
378
379 /* Ack the end-of-message interrupt */
380 out_be32((void *)&msg_regs->osr, RIO_MSG_OSR_EOMI);
381 }
382
383 out:
384 return IRQ_HANDLED;
385}
386
387/**
388 * rio_open_outb_mbox - Initialize MPC85xx outbound mailbox
389 * @mport: Master port implementing the outbound message unit
390 * @dev_id: Device specific pointer to pass on event
391 * @mbox: Mailbox to open
392 * @entries: Number of entries in the outbound mailbox ring
393 *
394 * Initializes buffer ring, request the outbound message interrupt,
395 * and enables the outbound message unit. Returns %0 on success and
396 * %-EINVAL or %-ENOMEM on failure.
397 */
398int rio_open_outb_mbox(struct rio_mport *mport, void *dev_id, int mbox, int entries)
399{
400 int i, j, rc = 0;
401
402 if ((entries < RIO_MIN_TX_RING_SIZE) ||
403 (entries > RIO_MAX_TX_RING_SIZE) || (!is_power_of_2(entries))) {
404 rc = -EINVAL;
405 goto out;
406 }
407
408 /* Initialize shadow copy ring */
409 msg_tx_ring.dev_id = dev_id;
410 msg_tx_ring.size = entries;
411
412 for (i = 0; i < msg_tx_ring.size; i++) {
413 if (!
414 (msg_tx_ring.virt_buffer[i] =
415 dma_alloc_coherent(NULL, RIO_MSG_BUFFER_SIZE,
416 &msg_tx_ring.phys_buffer[i],
417 GFP_KERNEL))) {
418 rc = -ENOMEM;
419 for (j = 0; j < msg_tx_ring.size; j++)
420 if (msg_tx_ring.virt_buffer[j])
421 dma_free_coherent(NULL,
422 RIO_MSG_BUFFER_SIZE,
423 msg_tx_ring.
424 virt_buffer[j],
425 msg_tx_ring.
426 phys_buffer[j]);
427 goto out;
428 }
429 }
430
431 /* Initialize outbound message descriptor ring */
432 if (!(msg_tx_ring.virt = dma_alloc_coherent(NULL,
433 msg_tx_ring.size *
434 RIO_MSG_DESC_SIZE,
435 &msg_tx_ring.phys,
436 GFP_KERNEL))) {
437 rc = -ENOMEM;
438 goto out_dma;
439 }
440 memset(msg_tx_ring.virt, 0, msg_tx_ring.size * RIO_MSG_DESC_SIZE);
441 msg_tx_ring.tx_slot = 0;
442
443 /* Point dequeue/enqueue pointers at first entry in ring */
444 out_be32((void *)&msg_regs->odqdpar, msg_tx_ring.phys);
445 out_be32((void *)&msg_regs->odqepar, msg_tx_ring.phys);
446
447 /* Configure for snooping */
448 out_be32((void *)&msg_regs->osar, 0x00000004);
449
450 /* Clear interrupt status */
451 out_be32((void *)&msg_regs->osr, 0x000000b3);
452
453 /* Hook up outbound message handler */
454 if ((rc =
455 request_irq(MPC85xx_IRQ_RIO_TX, mpc85xx_rio_tx_handler, 0,
456 "msg_tx", (void *)mport)) < 0)
457 goto out_irq;
458
459 /*
460 * Configure outbound message unit
461 * Snooping
462 * Interrupts (all enabled, except QEIE)
463 * Chaining mode
464 * Disable
465 */
466 out_be32((void *)&msg_regs->omr, 0x00100220);
467
468 /* Set number of entries */
469 out_be32((void *)&msg_regs->omr,
470 in_be32((void *)&msg_regs->omr) |
471 ((get_bitmask_order(entries) - 2) << 12));
472
473 /* Now enable the unit */
474 out_be32((void *)&msg_regs->omr, in_be32((void *)&msg_regs->omr) | 0x1);
475
476 out:
477 return rc;
478
479 out_irq:
480 dma_free_coherent(NULL, msg_tx_ring.size * RIO_MSG_DESC_SIZE,
481 msg_tx_ring.virt, msg_tx_ring.phys);
482
483 out_dma:
484 for (i = 0; i < msg_tx_ring.size; i++)
485 dma_free_coherent(NULL, RIO_MSG_BUFFER_SIZE,
486 msg_tx_ring.virt_buffer[i],
487 msg_tx_ring.phys_buffer[i]);
488
489 return rc;
490}
491
492/**
493 * rio_close_outb_mbox - Shut down MPC85xx outbound mailbox
494 * @mport: Master port implementing the outbound message unit
495 * @mbox: Mailbox to close
496 *
497 * Disables the outbound message unit, free all buffers, and
498 * frees the outbound message interrupt.
499 */
500void rio_close_outb_mbox(struct rio_mport *mport, int mbox)
501{
502 /* Disable inbound message unit */
503 out_be32((void *)&msg_regs->omr, 0);
504
505 /* Free ring */
506 dma_free_coherent(NULL, msg_tx_ring.size * RIO_MSG_DESC_SIZE,
507 msg_tx_ring.virt, msg_tx_ring.phys);
508
509 /* Free interrupt */
510 free_irq(MPC85xx_IRQ_RIO_TX, (void *)mport);
511}
512
513/**
514 * mpc85xx_rio_rx_handler - MPC85xx inbound message interrupt handler
515 * @irq: Linux interrupt number
516 * @dev_instance: Pointer to interrupt-specific data
517 *
518 * Handles inbound message interrupts. Executes a registered inbound
519 * mailbox event handler and acks the interrupt occurrence.
520 */
521static irqreturn_t
522mpc85xx_rio_rx_handler(int irq, void *dev_instance)
523{
524 int isr;
525 struct rio_mport *port = (struct rio_mport *)dev_instance;
526
527 isr = in_be32((void *)&msg_regs->isr);
528
529 if (isr & RIO_MSG_ISR_TE) {
530 pr_info("RIO: inbound message reception error\n");
531 out_be32((void *)&msg_regs->isr, RIO_MSG_ISR_TE);
532 goto out;
533 }
534
535 /* XXX Need to check/dispatch until queue empty */
536 if (isr & RIO_MSG_ISR_DIQI) {
537 /*
538 * We implement *only* mailbox 0, but can receive messages
539 * for any mailbox/letter to that mailbox destination. So,
540 * make the callback with an unknown/invalid mailbox number
541 * argument.
542 */
543 port->inb_msg[0].mcback(port, msg_rx_ring.dev_id, -1, -1);
544
545 /* Ack the queueing interrupt */
546 out_be32((void *)&msg_regs->isr, RIO_MSG_ISR_DIQI);
547 }
548
549 out:
550 return IRQ_HANDLED;
551}
552
553/**
554 * rio_open_inb_mbox - Initialize MPC85xx inbound mailbox
555 * @mport: Master port implementing the inbound message unit
556 * @dev_id: Device specific pointer to pass on event
557 * @mbox: Mailbox to open
558 * @entries: Number of entries in the inbound mailbox ring
559 *
560 * Initializes buffer ring, request the inbound message interrupt,
561 * and enables the inbound message unit. Returns %0 on success
562 * and %-EINVAL or %-ENOMEM on failure.
563 */
564int rio_open_inb_mbox(struct rio_mport *mport, void *dev_id, int mbox, int entries)
565{
566 int i, rc = 0;
567
568 if ((entries < RIO_MIN_RX_RING_SIZE) ||
569 (entries > RIO_MAX_RX_RING_SIZE) || (!is_power_of_2(entries))) {
570 rc = -EINVAL;
571 goto out;
572 }
573
574 /* Initialize client buffer ring */
575 msg_rx_ring.dev_id = dev_id;
576 msg_rx_ring.size = entries;
577 msg_rx_ring.rx_slot = 0;
578 for (i = 0; i < msg_rx_ring.size; i++)
579 msg_rx_ring.virt_buffer[i] = NULL;
580
581 /* Initialize inbound message ring */
582 if (!(msg_rx_ring.virt = dma_alloc_coherent(NULL,
583 msg_rx_ring.size *
584 RIO_MAX_MSG_SIZE,
585 &msg_rx_ring.phys,
586 GFP_KERNEL))) {
587 rc = -ENOMEM;
588 goto out;
589 }
590
591 /* Point dequeue/enqueue pointers at first entry in ring */
592 out_be32((void *)&msg_regs->ifqdpar, (u32) msg_rx_ring.phys);
593 out_be32((void *)&msg_regs->ifqepar, (u32) msg_rx_ring.phys);
594
595 /* Clear interrupt status */
596 out_be32((void *)&msg_regs->isr, 0x00000091);
597
598 /* Hook up inbound message handler */
599 if ((rc =
600 request_irq(MPC85xx_IRQ_RIO_RX, mpc85xx_rio_rx_handler, 0,
601 "msg_rx", (void *)mport)) < 0) {
602 dma_free_coherent(NULL, RIO_MSG_BUFFER_SIZE,
603 msg_tx_ring.virt_buffer[i],
604 msg_tx_ring.phys_buffer[i]);
605 goto out;
606 }
607
608 /*
609 * Configure inbound message unit:
610 * Snooping
611 * 4KB max message size
612 * Unmask all interrupt sources
613 * Disable
614 */
615 out_be32((void *)&msg_regs->imr, 0x001b0060);
616
617 /* Set number of queue entries */
618 out_be32((void *)&msg_regs->imr,
619 in_be32((void *)&msg_regs->imr) |
620 ((get_bitmask_order(entries) - 2) << 12));
621
622 /* Now enable the unit */
623 out_be32((void *)&msg_regs->imr, in_be32((void *)&msg_regs->imr) | 0x1);
624
625 out:
626 return rc;
627}
628
629/**
630 * rio_close_inb_mbox - Shut down MPC85xx inbound mailbox
631 * @mport: Master port implementing the inbound message unit
632 * @mbox: Mailbox to close
633 *
634 * Disables the inbound message unit, free all buffers, and
635 * frees the inbound message interrupt.
636 */
637void rio_close_inb_mbox(struct rio_mport *mport, int mbox)
638{
639 /* Disable inbound message unit */
640 out_be32((void *)&msg_regs->imr, 0);
641
642 /* Free ring */
643 dma_free_coherent(NULL, msg_rx_ring.size * RIO_MAX_MSG_SIZE,
644 msg_rx_ring.virt, msg_rx_ring.phys);
645
646 /* Free interrupt */
647 free_irq(MPC85xx_IRQ_RIO_RX, (void *)mport);
648}
649
650/**
651 * rio_hw_add_inb_buffer - Add buffer to the MPC85xx inbound message queue
652 * @mport: Master port implementing the inbound message unit
653 * @mbox: Inbound mailbox number
654 * @buf: Buffer to add to inbound queue
655 *
656 * Adds the @buf buffer to the MPC85xx inbound message queue. Returns
657 * %0 on success or %-EINVAL on failure.
658 */
659int rio_hw_add_inb_buffer(struct rio_mport *mport, int mbox, void *buf)
660{
661 int rc = 0;
662
663 pr_debug("RIO: rio_hw_add_inb_buffer(), msg_rx_ring.rx_slot %d\n",
664 msg_rx_ring.rx_slot);
665
666 if (msg_rx_ring.virt_buffer[msg_rx_ring.rx_slot]) {
667 printk(KERN_ERR
668 "RIO: error adding inbound buffer %d, buffer exists\n",
669 msg_rx_ring.rx_slot);
670 rc = -EINVAL;
671 goto out;
672 }
673
674 msg_rx_ring.virt_buffer[msg_rx_ring.rx_slot] = buf;
675 if (++msg_rx_ring.rx_slot == msg_rx_ring.size)
676 msg_rx_ring.rx_slot = 0;
677
678 out:
679 return rc;
680}
681
682EXPORT_SYMBOL_GPL(rio_hw_add_inb_buffer);
683
684/**
685 * rio_hw_get_inb_message - Fetch inbound message from the MPC85xx message unit
686 * @mport: Master port implementing the inbound message unit
687 * @mbox: Inbound mailbox number
688 *
689 * Gets the next available inbound message from the inbound message queue.
690 * A pointer to the message is returned on success or NULL on failure.
691 */
692void *rio_hw_get_inb_message(struct rio_mport *mport, int mbox)
693{
694 u32 imr;
695 u32 phys_buf, virt_buf;
696 void *buf = NULL;
697 int buf_idx;
698
699 phys_buf = in_be32((void *)&msg_regs->ifqdpar);
700
701 /* If no more messages, then bail out */
702 if (phys_buf == in_be32((void *)&msg_regs->ifqepar))
703 goto out2;
704
705 virt_buf = (u32) msg_rx_ring.virt + (phys_buf - msg_rx_ring.phys);
706 buf_idx = (phys_buf - msg_rx_ring.phys) / RIO_MAX_MSG_SIZE;
707 buf = msg_rx_ring.virt_buffer[buf_idx];
708
709 if (!buf) {
710 printk(KERN_ERR
711 "RIO: inbound message copy failed, no buffers\n");
712 goto out1;
713 }
714
715 /* Copy max message size, caller is expected to allocate that big */
716 memcpy(buf, (void *)virt_buf, RIO_MAX_MSG_SIZE);
717
718 /* Clear the available buffer */
719 msg_rx_ring.virt_buffer[buf_idx] = NULL;
720
721 out1:
722 imr = in_be32((void *)&msg_regs->imr);
723 out_be32((void *)&msg_regs->imr, imr | RIO_MSG_IMR_MI);
724
725 out2:
726 return buf;
727}
728
729EXPORT_SYMBOL_GPL(rio_hw_get_inb_message);
730
731/**
732 * mpc85xx_rio_dbell_handler - MPC85xx doorbell interrupt handler
733 * @irq: Linux interrupt number
734 * @dev_instance: Pointer to interrupt-specific data
735 *
736 * Handles doorbell interrupts. Parses a list of registered
737 * doorbell event handlers and executes a matching event handler.
738 */
739static irqreturn_t
740mpc85xx_rio_dbell_handler(int irq, void *dev_instance)
741{
742 int dsr;
743 struct rio_mport *port = (struct rio_mport *)dev_instance;
744
745 dsr = in_be32((void *)&msg_regs->dsr);
746
747 if (dsr & DOORBELL_DSR_TE) {
748 pr_info("RIO: doorbell reception error\n");
749 out_be32((void *)&msg_regs->dsr, DOORBELL_DSR_TE);
750 goto out;
751 }
752
753 if (dsr & DOORBELL_DSR_QFI) {
754 pr_info("RIO: doorbell queue full\n");
755 out_be32((void *)&msg_regs->dsr, DOORBELL_DSR_QFI);
756 goto out;
757 }
758
759 /* XXX Need to check/dispatch until queue empty */
760 if (dsr & DOORBELL_DSR_DIQI) {
761 u32 dmsg =
762 (u32) dbell_ring.virt +
763 (in_be32((void *)&msg_regs->dqdpar) & 0xfff);
764 u32 dmr;
765 struct rio_dbell *dbell;
766 int found = 0;
767
768 pr_debug
769 ("RIO: processing doorbell, sid %2.2x tid %2.2x info %4.4x\n",
770 DBELL_SID(dmsg), DBELL_TID(dmsg), DBELL_INF(dmsg));
771
772 list_for_each_entry(dbell, &port->dbells, node) {
773 if ((dbell->res->start <= DBELL_INF(dmsg)) &&
774 (dbell->res->end >= DBELL_INF(dmsg))) {
775 found = 1;
776 break;
777 }
778 }
779 if (found) {
780 dbell->dinb(port, dbell->dev_id, DBELL_SID(dmsg), DBELL_TID(dmsg),
781 DBELL_INF(dmsg));
782 } else {
783 pr_debug
784 ("RIO: spurious doorbell, sid %2.2x tid %2.2x info %4.4x\n",
785 DBELL_SID(dmsg), DBELL_TID(dmsg), DBELL_INF(dmsg));
786 }
787 dmr = in_be32((void *)&msg_regs->dmr);
788 out_be32((void *)&msg_regs->dmr, dmr | DOORBELL_DMR_DI);
789 out_be32((void *)&msg_regs->dsr, DOORBELL_DSR_DIQI);
790 }
791
792 out:
793 return IRQ_HANDLED;
794}
795
796/**
797 * mpc85xx_rio_doorbell_init - MPC85xx doorbell interface init
798 * @mport: Master port implementing the inbound doorbell unit
799 *
800 * Initializes doorbell unit hardware and inbound DMA buffer
801 * ring. Called from mpc85xx_rio_setup(). Returns %0 on success
802 * or %-ENOMEM on failure.
803 */
804static int mpc85xx_rio_doorbell_init(struct rio_mport *mport)
805{
806 int rc = 0;
807
808 /* Map outbound doorbell window immediately after maintenance window */
809 if (!(dbell_win =
810 (u32) ioremap(mport->iores.start + RIO_MAINT_WIN_SIZE,
811 RIO_DBELL_WIN_SIZE))) {
812 printk(KERN_ERR
813 "RIO: unable to map outbound doorbell window\n");
814 rc = -ENOMEM;
815 goto out;
816 }
817
818 /* Initialize inbound doorbells */
819 if (!(dbell_ring.virt = dma_alloc_coherent(NULL,
820 512 * DOORBELL_MESSAGE_SIZE,
821 &dbell_ring.phys,
822 GFP_KERNEL))) {
823 printk(KERN_ERR "RIO: unable allocate inbound doorbell ring\n");
824 rc = -ENOMEM;
825 iounmap((void *)dbell_win);
826 goto out;
827 }
828
829 /* Point dequeue/enqueue pointers at first entry in ring */
830 out_be32((void *)&msg_regs->dqdpar, (u32) dbell_ring.phys);
831 out_be32((void *)&msg_regs->dqepar, (u32) dbell_ring.phys);
832
833 /* Clear interrupt status */
834 out_be32((void *)&msg_regs->dsr, 0x00000091);
835
836 /* Hook up doorbell handler */
837 if ((rc =
838 request_irq(MPC85xx_IRQ_RIO_BELL, mpc85xx_rio_dbell_handler, 0,
839 "dbell_rx", (void *)mport) < 0)) {
840 iounmap((void *)dbell_win);
841 dma_free_coherent(NULL, 512 * DOORBELL_MESSAGE_SIZE,
842 dbell_ring.virt, dbell_ring.phys);
843 printk(KERN_ERR
844 "MPC85xx RIO: unable to request inbound doorbell irq");
845 goto out;
846 }
847
848 /* Configure doorbells for snooping, 512 entries, and enable */
849 out_be32((void *)&msg_regs->dmr, 0x00108161);
850
851 out:
852 return rc;
853}
854
855static char *cmdline = NULL;
856
857static int mpc85xx_rio_get_hdid(int index)
858{
859 /* XXX Need to parse multiple entries in some format */
860 if (!cmdline)
861 return -1;
862
863 return simple_strtol(cmdline, NULL, 0);
864}
865
866static int mpc85xx_rio_get_cmdline(char *s)
867{
868 if (!s)
869 return 0;
870
871 cmdline = s;
872 return 1;
873}
874
875__setup("riohdid=", mpc85xx_rio_get_cmdline);
876
877/**
878 * mpc85xx_rio_setup - Setup MPC85xx RapidIO interface
879 * @law_start: Starting physical address of RapidIO LAW
880 * @law_size: Size of RapidIO LAW
881 *
882 * Initializes MPC85xx RapidIO hardware interface, configures
883 * master port with system-specific info, and registers the
884 * master port with the RapidIO subsystem.
885 */
886void mpc85xx_rio_setup(int law_start, int law_size)
887{
888 struct rio_ops *ops;
889 struct rio_mport *port;
890
891 ops = kmalloc(sizeof(struct rio_ops), GFP_KERNEL);
892 ops->lcread = mpc85xx_local_config_read;
893 ops->lcwrite = mpc85xx_local_config_write;
894 ops->cread = mpc85xx_rio_config_read;
895 ops->cwrite = mpc85xx_rio_config_write;
896 ops->dsend = mpc85xx_rio_doorbell_send;
897
898 port = kmalloc(sizeof(struct rio_mport), GFP_KERNEL);
899 port->id = 0;
900 port->index = 0;
901 INIT_LIST_HEAD(&port->dbells);
902 port->iores.start = law_start;
903 port->iores.end = law_start + law_size;
904 port->iores.flags = IORESOURCE_MEM;
905
906 rio_init_dbell_res(&port->riores[RIO_DOORBELL_RESOURCE], 0, 0xffff);
907 rio_init_mbox_res(&port->riores[RIO_INB_MBOX_RESOURCE], 0, 0);
908 rio_init_mbox_res(&port->riores[RIO_OUTB_MBOX_RESOURCE], 0, 0);
909 strcpy(port->name, "RIO0 mport");
910
911 port->ops = ops;
912 port->host_deviceid = mpc85xx_rio_get_hdid(port->id);
913
914 rio_register_mport(port);
915
916 regs_win = (u32) ioremap(RIO_REGS_BASE, 0x20000);
917 atmu_regs = (struct rio_atmu_regs *)(regs_win + RIO_ATMU_REGS_OFFSET);
918 maint_atmu_regs = atmu_regs + 1;
919 dbell_atmu_regs = atmu_regs + 2;
920 msg_regs = (struct rio_msg_regs *)(regs_win + RIO_MSG_REGS_OFFSET);
921
922 /* Configure maintenance transaction window */
923 out_be32((void *)&maint_atmu_regs->rowbar, 0x000c0000);
924 out_be32((void *)&maint_atmu_regs->rowar, 0x80077015);
925
926 maint_win = (u32) ioremap(law_start, RIO_MAINT_WIN_SIZE);
927
928 /* Configure outbound doorbell window */
929 out_be32((void *)&dbell_atmu_regs->rowbar, 0x000c0400);
930 out_be32((void *)&dbell_atmu_regs->rowar, 0x8004200b);
931 mpc85xx_rio_doorbell_init(port);
932}
diff --git a/arch/powerpc/sysdev/fsl_rio.h b/arch/powerpc/sysdev/fsl_rio.h
new file mode 100644
index 000000000000..6d3ff30b1579
--- /dev/null
+++ b/arch/powerpc/sysdev/fsl_rio.h
@@ -0,0 +1,20 @@
1/*
2 * MPC85xx RapidIO definitions
3 *
4 * Copyright 2005 MontaVista Software, Inc.
5 * Matt Porter <mporter@kernel.crashing.org>
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version.
11 */
12
13#ifndef __PPC_SYSLIB_PPC85XX_RIO_H
14#define __PPC_SYSLIB_PPC85XX_RIO_H
15
16#include <linux/init.h>
17
18extern void mpc85xx_rio_setup(int law_start, int law_size);
19
20#endif /* __PPC_SYSLIB_PPC85XX_RIO_H */