aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/sysdev
diff options
context:
space:
mode:
authorLi Yang <leoli@freescale.com>2006-10-04 00:10:46 -0400
committerPaul Mackerras <paulus@samba.org>2006-10-04 01:24:27 -0400
commit9865853851313e0d94a4acde42d6f9d8070bb376 (patch)
tree0f4cca2bda6d2a21b8beb02ec2883bf328f1935c /arch/powerpc/sysdev
parent9a1ab883c04e43f9f9819c40eb435bcdc4136193 (diff)
[POWERPC] Add QUICC Engine (QE) infrastructure
Add QUICC Engine (QE) configuration, header files, and QE management and library code that are used by QE devices drivers. Includes Leo's modifications up to, and including, the platform_device to of_device adaptation: "The series of patches add generic QE infrastructure called qe_lib, and MPC8360EMDS board support. Qe_lib is used by QE device drivers such as ucc_geth driver. This version updates QE interrupt controller to use new irq mapping mechanism, addresses all the comments received with last submission and includes some style fixes. v2: Change to use device tree for BCSR and MURAM; Remove I/O port interrupt handling code as it is not generic enough. v3: Address comments from Kumar; Update definition of several device tree nodes; Copyright style change." In addition, the following changes have been made: o removed typedefs o uint -> u32 conversions o removed following defines: QE_SIZEOF_BD, BD_BUFFER_ARG, BD_BUFFER_CLEAR, BD_BUFFER, BD_STATUS_AND_LENGTH_SET, BD_STATUS_AND_LENGTH, and BD_BUFFER_SET because they hid sizeof/in_be32/out_be32 operations from the reader. o fixed qe_snums_init() serial num assignment to use a const array o made CONFIG_UCC_FAST select UCC_SLOW o reduced NR_QE_IC_INTS from 128 to 64 o remove _IO_BASE, etc. defines (not used) o removed irrelevant comments, added others to resemble removed BD_ defines o realigned struct definitions in headers o various other style fixes including things like pinMask -> pin_mask o fixed a ton of whitespace issues o marked ioregs as __be32/__be16 o removed platform_device code and redundant get_qe_base() o removed redundant comments o added cpu_relax() to qe_reset o uncasted all get_property() assignments o eliminated unneeded casts o eliminated immrbar_phys_to_virt (not used) Signed-off-by: Li Yang <leoli@freescale.com> Signed-off-by: Shlomi Gridish <gridish@freescale.com> Signed-off-by: Kim Phillips <kim.phillips@freescale.com> Signed-off-by: Paul Mackerras <paulus@samba.org>
Diffstat (limited to 'arch/powerpc/sysdev')
-rw-r--r--arch/powerpc/sysdev/Makefile1
-rw-r--r--arch/powerpc/sysdev/qe_lib/Kconfig30
-rw-r--r--arch/powerpc/sysdev/qe_lib/Makefile8
-rw-r--r--arch/powerpc/sysdev/qe_lib/qe.c353
-rw-r--r--arch/powerpc/sysdev/qe_lib/qe_ic.c555
-rw-r--r--arch/powerpc/sysdev/qe_lib/qe_ic.h106
-rw-r--r--arch/powerpc/sysdev/qe_lib/qe_io.c226
-rw-r--r--arch/powerpc/sysdev/qe_lib/ucc.c251
-rw-r--r--arch/powerpc/sysdev/qe_lib/ucc_fast.c396
-rw-r--r--arch/powerpc/sysdev/qe_lib/ucc_slow.c404
10 files changed, 2330 insertions, 0 deletions
diff --git a/arch/powerpc/sysdev/Makefile b/arch/powerpc/sysdev/Makefile
index f15f4d78aee9..91f052d8cce0 100644
--- a/arch/powerpc/sysdev/Makefile
+++ b/arch/powerpc/sysdev/Makefile
@@ -12,6 +12,7 @@ obj-$(CONFIG_MMIO_NVRAM) += mmio_nvram.o
12obj-$(CONFIG_FSL_SOC) += fsl_soc.o 12obj-$(CONFIG_FSL_SOC) += fsl_soc.o
13obj-$(CONFIG_PPC_TODC) += todc.o 13obj-$(CONFIG_PPC_TODC) += todc.o
14obj-$(CONFIG_TSI108_BRIDGE) += tsi108_pci.o tsi108_dev.o 14obj-$(CONFIG_TSI108_BRIDGE) += tsi108_pci.o tsi108_dev.o
15obj-$(CONFIG_QUICC_ENGINE) += qe_lib/
15 16
16ifeq ($(CONFIG_PPC_MERGE),y) 17ifeq ($(CONFIG_PPC_MERGE),y)
17obj-$(CONFIG_PPC_I8259) += i8259.o 18obj-$(CONFIG_PPC_I8259) += i8259.o
diff --git a/arch/powerpc/sysdev/qe_lib/Kconfig b/arch/powerpc/sysdev/qe_lib/Kconfig
new file mode 100644
index 000000000000..a725e80befa8
--- /dev/null
+++ b/arch/powerpc/sysdev/qe_lib/Kconfig
@@ -0,0 +1,30 @@
1#
2# QE Communication options
3#
4
5menu "QE Options"
6 depends on QUICC_ENGINE
7
8config UCC_SLOW
9 bool "UCC Slow Protocols Support"
10 default n
11 select UCC
12 help
13 This option provides qe_lib support to UCC slow
14 protocols: UART, BISYNC, QMC
15
16config UCC_FAST
17 bool "UCC Fast Protocols Support"
18 default n
19 select UCC
20 select UCC_SLOW
21 help
22 This option provides qe_lib support to UCC fast
23 protocols: HDLC, Ethernet, ATM, transparent
24
25config UCC
26 bool
27 default y if UCC_FAST || UCC_SLOW
28
29endmenu
30
diff --git a/arch/powerpc/sysdev/qe_lib/Makefile b/arch/powerpc/sysdev/qe_lib/Makefile
new file mode 100644
index 000000000000..874fe1a5b1cf
--- /dev/null
+++ b/arch/powerpc/sysdev/qe_lib/Makefile
@@ -0,0 +1,8 @@
1#
2# Makefile for the linux ppc-specific parts of QE
3#
4obj-$(CONFIG_QUICC_ENGINE)+= qe.o qe_ic.o qe_io.o
5
6obj-$(CONFIG_UCC) += ucc.o
7obj-$(CONFIG_UCC_SLOW) += ucc_slow.o
8obj-$(CONFIG_UCC_FAST) += ucc_fast.o
diff --git a/arch/powerpc/sysdev/qe_lib/qe.c b/arch/powerpc/sysdev/qe_lib/qe.c
new file mode 100644
index 000000000000..2bae632d3ad7
--- /dev/null
+++ b/arch/powerpc/sysdev/qe_lib/qe.c
@@ -0,0 +1,353 @@
1/*
2 * Copyright (C) 2006 Freescale Semicondutor, Inc. All rights reserved.
3 *
4 * Authors: Shlomi Gridish <gridish@freescale.com>
5 * Li Yang <leoli@freescale.com>
6 * Based on cpm2_common.c from Dan Malek (dmalek@jlc.net)
7 *
8 * Description:
9 * General Purpose functions for the global management of the
10 * QUICC Engine (QE).
11 *
12 * This program is free software; you can redistribute it and/or modify it
13 * under the terms of the GNU General Public License as published by the
14 * Free Software Foundation; either version 2 of the License, or (at your
15 * option) any later version.
16 */
17#include <linux/errno.h>
18#include <linux/sched.h>
19#include <linux/kernel.h>
20#include <linux/param.h>
21#include <linux/string.h>
22#include <linux/mm.h>
23#include <linux/interrupt.h>
24#include <linux/bootmem.h>
25#include <linux/module.h>
26#include <linux/delay.h>
27#include <linux/ioport.h>
28#include <asm/irq.h>
29#include <asm/page.h>
30#include <asm/pgtable.h>
31#include <asm/immap_qe.h>
32#include <asm/qe.h>
33#include <asm/prom.h>
34#include <asm/rheap.h>
35
36static void qe_snums_init(void);
37static void qe_muram_init(void);
38static int qe_sdma_init(void);
39
40static DEFINE_SPINLOCK(qe_lock);
41
42/* QE snum state */
43enum qe_snum_state {
44 QE_SNUM_STATE_USED,
45 QE_SNUM_STATE_FREE
46};
47
48/* QE snum */
49struct qe_snum {
50 u8 num;
51 enum qe_snum_state state;
52};
53
54/* We allocate this here because it is used almost exclusively for
55 * the communication processor devices.
56 */
57struct qe_immap *qe_immr = NULL;
58EXPORT_SYMBOL(qe_immr);
59
60static struct qe_snum snums[QE_NUM_OF_SNUM]; /* Dynamically allocated SNUMs */
61
62static phys_addr_t qebase = -1;
63
64phys_addr_t get_qe_base(void)
65{
66 struct device_node *qe;
67
68 if (qebase != -1)
69 return qebase;
70
71 qe = of_find_node_by_type(NULL, "qe");
72 if (qe) {
73 unsigned int size;
74 const void *prop = get_property(qe, "reg", &size);
75 qebase = of_translate_address(qe, prop);
76 of_node_put(qe);
77 };
78
79 return qebase;
80}
81
82EXPORT_SYMBOL(get_qe_base);
83
84void qe_reset(void)
85{
86 if (qe_immr == NULL)
87 qe_immr = ioremap(get_qe_base(), QE_IMMAP_SIZE);
88
89 qe_snums_init();
90
91 qe_issue_cmd(QE_RESET, QE_CR_SUBBLOCK_INVALID,
92 QE_CR_PROTOCOL_UNSPECIFIED, 0);
93
94 /* Reclaim the MURAM memory for our use. */
95 qe_muram_init();
96
97 if (qe_sdma_init())
98 panic("sdma init failed!");
99}
100
101int qe_issue_cmd(u32 cmd, u32 device, u8 mcn_protocol, u32 cmd_input)
102{
103 unsigned long flags;
104 u8 mcn_shift = 0, dev_shift = 0;
105
106 spin_lock_irqsave(&qe_lock, flags);
107 if (cmd == QE_RESET) {
108 out_be32(&qe_immr->cp.cecr, (u32) (cmd | QE_CR_FLG));
109 } else {
110 if (cmd == QE_ASSIGN_PAGE) {
111 /* Here device is the SNUM, not sub-block */
112 dev_shift = QE_CR_SNUM_SHIFT;
113 } else if (cmd == QE_ASSIGN_RISC) {
114 /* Here device is the SNUM, and mcnProtocol is
115 * e_QeCmdRiscAssignment value */
116 dev_shift = QE_CR_SNUM_SHIFT;
117 mcn_shift = QE_CR_MCN_RISC_ASSIGN_SHIFT;
118 } else {
119 if (device == QE_CR_SUBBLOCK_USB)
120 mcn_shift = QE_CR_MCN_USB_SHIFT;
121 else
122 mcn_shift = QE_CR_MCN_NORMAL_SHIFT;
123 }
124
125 out_be32(&qe_immr->cp.cecdr,
126 immrbar_virt_to_phys((void *)cmd_input));
127 out_be32(&qe_immr->cp.cecr,
128 (cmd | QE_CR_FLG | ((u32) device << dev_shift) | (u32)
129 mcn_protocol << mcn_shift));
130 }
131
132 /* wait for the QE_CR_FLG to clear */
133 while(in_be32(&qe_immr->cp.cecr) & QE_CR_FLG)
134 cpu_relax();
135 spin_unlock_irqrestore(&qe_lock, flags);
136
137 return 0;
138}
139EXPORT_SYMBOL(qe_issue_cmd);
140
141/* Set a baud rate generator. This needs lots of work. There are
142 * 16 BRGs, which can be connected to the QE channels or output
143 * as clocks. The BRGs are in two different block of internal
144 * memory mapped space.
145 * The baud rate clock is the system clock divided by something.
146 * It was set up long ago during the initial boot phase and is
147 * is given to us.
148 * Baud rate clocks are zero-based in the driver code (as that maps
149 * to port numbers). Documentation uses 1-based numbering.
150 */
151static unsigned int brg_clk = 0;
152
153unsigned int get_brg_clk(void)
154{
155 struct device_node *qe;
156 if (brg_clk)
157 return brg_clk;
158
159 qe = of_find_node_by_type(NULL, "qe");
160 if (qe) {
161 unsigned int size;
162 const u32 *prop = get_property(qe, "brg-frequency", &size);
163 brg_clk = *prop;
164 of_node_put(qe);
165 };
166 return brg_clk;
167}
168
169/* This function is used by UARTS, or anything else that uses a 16x
170 * oversampled clock.
171 */
172void qe_setbrg(u32 brg, u32 rate)
173{
174 volatile u32 *bp;
175 u32 divisor, tempval;
176 int div16 = 0;
177
178 bp = &qe_immr->brg.brgc1;
179 bp += brg;
180
181 divisor = (get_brg_clk() / rate);
182 if (divisor > QE_BRGC_DIVISOR_MAX + 1) {
183 div16 = 1;
184 divisor /= 16;
185 }
186
187 tempval = ((divisor - 1) << QE_BRGC_DIVISOR_SHIFT) | QE_BRGC_ENABLE;
188 if (div16)
189 tempval |= QE_BRGC_DIV16;
190
191 out_be32(bp, tempval);
192}
193
194/* Initialize SNUMs (thread serial numbers) according to
195 * QE Module Control chapter, SNUM table
196 */
197static void qe_snums_init(void)
198{
199 int i;
200 static const u8 snum_init[] = {
201 0x04, 0x05, 0x0C, 0x0D, 0x14, 0x15, 0x1C, 0x1D,
202 0x24, 0x25, 0x2C, 0x2D, 0x34, 0x35, 0x88, 0x89,
203 0x98, 0x99, 0xA8, 0xA9, 0xB8, 0xB9, 0xC8, 0xC9,
204 0xD8, 0xD9, 0xE8, 0xE9,
205 };
206
207 for (i = 0; i < QE_NUM_OF_SNUM; i++) {
208 snums[i].num = snum_init[i];
209 snums[i].state = QE_SNUM_STATE_FREE;
210 }
211}
212
213int qe_get_snum(void)
214{
215 unsigned long flags;
216 int snum = -EBUSY;
217 int i;
218
219 spin_lock_irqsave(&qe_lock, flags);
220 for (i = 0; i < QE_NUM_OF_SNUM; i++) {
221 if (snums[i].state == QE_SNUM_STATE_FREE) {
222 snums[i].state = QE_SNUM_STATE_USED;
223 snum = snums[i].num;
224 break;
225 }
226 }
227 spin_unlock_irqrestore(&qe_lock, flags);
228
229 return snum;
230}
231EXPORT_SYMBOL(qe_get_snum);
232
233void qe_put_snum(u8 snum)
234{
235 int i;
236
237 for (i = 0; i < QE_NUM_OF_SNUM; i++) {
238 if (snums[i].num == snum) {
239 snums[i].state = QE_SNUM_STATE_FREE;
240 break;
241 }
242 }
243}
244EXPORT_SYMBOL(qe_put_snum);
245
246static int qe_sdma_init(void)
247{
248 struct sdma *sdma = &qe_immr->sdma;
249 u32 sdma_buf_offset;
250
251 if (!sdma)
252 return -ENODEV;
253
254 /* allocate 2 internal temporary buffers (512 bytes size each) for
255 * the SDMA */
256 sdma_buf_offset = qe_muram_alloc(512 * 2, 64);
257 if (IS_MURAM_ERR(sdma_buf_offset))
258 return -ENOMEM;
259
260 out_be32(&sdma->sdebcr, sdma_buf_offset & QE_SDEBCR_BA_MASK);
261 out_be32(&sdma->sdmr, (QE_SDMR_GLB_1_MSK | (0x1 >>
262 QE_SDMR_CEN_SHIFT)));
263
264 return 0;
265}
266
267/*
268 * muram_alloc / muram_free bits.
269 */
270static DEFINE_SPINLOCK(qe_muram_lock);
271
272/* 16 blocks should be enough to satisfy all requests
273 * until the memory subsystem goes up... */
274static rh_block_t qe_boot_muram_rh_block[16];
275static rh_info_t qe_muram_info;
276
277static void qe_muram_init(void)
278{
279 struct device_node *np;
280 u32 address;
281 u64 size;
282 unsigned int flags;
283
284 /* initialize the info header */
285 rh_init(&qe_muram_info, 1,
286 sizeof(qe_boot_muram_rh_block) /
287 sizeof(qe_boot_muram_rh_block[0]), qe_boot_muram_rh_block);
288
289 /* Attach the usable muram area */
290 /* XXX: This is a subset of the available muram. It
291 * varies with the processor and the microcode patches activated.
292 */
293 if ((np = of_find_node_by_name(NULL, "data-only")) != NULL) {
294 address = *of_get_address(np, 0, &size, &flags);
295 of_node_put(np);
296 rh_attach_region(&qe_muram_info,
297 (void *)address, (int)size);
298 }
299}
300
301/* This function returns an index into the MURAM area.
302 */
303u32 qe_muram_alloc(u32 size, u32 align)
304{
305 void *start;
306 unsigned long flags;
307
308 spin_lock_irqsave(&qe_muram_lock, flags);
309 start = rh_alloc_align(&qe_muram_info, size, align, "QE");
310 spin_unlock_irqrestore(&qe_muram_lock, flags);
311
312 return (u32) start;
313}
314EXPORT_SYMBOL(qe_muram_alloc);
315
316int qe_muram_free(u32 offset)
317{
318 int ret;
319 unsigned long flags;
320
321 spin_lock_irqsave(&qe_muram_lock, flags);
322 ret = rh_free(&qe_muram_info, (void *)offset);
323 spin_unlock_irqrestore(&qe_muram_lock, flags);
324
325 return ret;
326}
327EXPORT_SYMBOL(qe_muram_free);
328
329/* not sure if this is ever needed */
330u32 qe_muram_alloc_fixed(u32 offset, u32 size)
331{
332 void *start;
333 unsigned long flags;
334
335 spin_lock_irqsave(&qe_muram_lock, flags);
336 start = rh_alloc_fixed(&qe_muram_info, (void *)offset, size, "commproc");
337 spin_unlock_irqrestore(&qe_muram_lock, flags);
338
339 return (u32) start;
340}
341EXPORT_SYMBOL(qe_muram_alloc_fixed);
342
343void qe_muram_dump(void)
344{
345 rh_dump(&qe_muram_info);
346}
347EXPORT_SYMBOL(qe_muram_dump);
348
349void *qe_muram_addr(u32 offset)
350{
351 return (void *)&qe_immr->muram[offset];
352}
353EXPORT_SYMBOL(qe_muram_addr);
diff --git a/arch/powerpc/sysdev/qe_lib/qe_ic.c b/arch/powerpc/sysdev/qe_lib/qe_ic.c
new file mode 100644
index 000000000000..c229d07d4957
--- /dev/null
+++ b/arch/powerpc/sysdev/qe_lib/qe_ic.c
@@ -0,0 +1,555 @@
1/*
2 * arch/powerpc/sysdev/qe_lib/qe_ic.c
3 *
4 * Copyright (C) 2006 Freescale Semicondutor, Inc. All rights reserved.
5 *
6 * Author: Li Yang <leoli@freescale.com>
7 * Based on code from Shlomi Gridish <gridish@freescale.com>
8 *
9 * QUICC ENGINE Interrupt Controller
10 *
11 * This program is free software; you can redistribute it and/or modify it
12 * under the terms of the GNU General Public License as published by the
13 * Free Software Foundation; either version 2 of the License, or (at your
14 * option) any later version.
15 */
16
17#include <linux/kernel.h>
18#include <linux/init.h>
19#include <linux/errno.h>
20#include <linux/reboot.h>
21#include <linux/slab.h>
22#include <linux/stddef.h>
23#include <linux/sched.h>
24#include <linux/signal.h>
25#include <linux/sysdev.h>
26#include <linux/device.h>
27#include <linux/bootmem.h>
28#include <linux/spinlock.h>
29#include <asm/irq.h>
30#include <asm/io.h>
31#include <asm/prom.h>
32#include <asm/qe_ic.h>
33
34#include "qe_ic.h"
35
36static DEFINE_SPINLOCK(qe_ic_lock);
37
38static struct qe_ic_info qe_ic_info[] = {
39 [1] = {
40 .mask = 0x00008000,
41 .mask_reg = QEIC_CIMR,
42 .pri_code = 0,
43 .pri_reg = QEIC_CIPWCC,
44 },
45 [2] = {
46 .mask = 0x00004000,
47 .mask_reg = QEIC_CIMR,
48 .pri_code = 1,
49 .pri_reg = QEIC_CIPWCC,
50 },
51 [3] = {
52 .mask = 0x00002000,
53 .mask_reg = QEIC_CIMR,
54 .pri_code = 2,
55 .pri_reg = QEIC_CIPWCC,
56 },
57 [10] = {
58 .mask = 0x00000040,
59 .mask_reg = QEIC_CIMR,
60 .pri_code = 1,
61 .pri_reg = QEIC_CIPZCC,
62 },
63 [11] = {
64 .mask = 0x00000020,
65 .mask_reg = QEIC_CIMR,
66 .pri_code = 2,
67 .pri_reg = QEIC_CIPZCC,
68 },
69 [12] = {
70 .mask = 0x00000010,
71 .mask_reg = QEIC_CIMR,
72 .pri_code = 3,
73 .pri_reg = QEIC_CIPZCC,
74 },
75 [13] = {
76 .mask = 0x00000008,
77 .mask_reg = QEIC_CIMR,
78 .pri_code = 4,
79 .pri_reg = QEIC_CIPZCC,
80 },
81 [14] = {
82 .mask = 0x00000004,
83 .mask_reg = QEIC_CIMR,
84 .pri_code = 5,
85 .pri_reg = QEIC_CIPZCC,
86 },
87 [15] = {
88 .mask = 0x00000002,
89 .mask_reg = QEIC_CIMR,
90 .pri_code = 6,
91 .pri_reg = QEIC_CIPZCC,
92 },
93 [20] = {
94 .mask = 0x10000000,
95 .mask_reg = QEIC_CRIMR,
96 .pri_code = 3,
97 .pri_reg = QEIC_CIPRTA,
98 },
99 [25] = {
100 .mask = 0x00800000,
101 .mask_reg = QEIC_CRIMR,
102 .pri_code = 0,
103 .pri_reg = QEIC_CIPRTB,
104 },
105 [26] = {
106 .mask = 0x00400000,
107 .mask_reg = QEIC_CRIMR,
108 .pri_code = 1,
109 .pri_reg = QEIC_CIPRTB,
110 },
111 [27] = {
112 .mask = 0x00200000,
113 .mask_reg = QEIC_CRIMR,
114 .pri_code = 2,
115 .pri_reg = QEIC_CIPRTB,
116 },
117 [28] = {
118 .mask = 0x00100000,
119 .mask_reg = QEIC_CRIMR,
120 .pri_code = 3,
121 .pri_reg = QEIC_CIPRTB,
122 },
123 [32] = {
124 .mask = 0x80000000,
125 .mask_reg = QEIC_CIMR,
126 .pri_code = 0,
127 .pri_reg = QEIC_CIPXCC,
128 },
129 [33] = {
130 .mask = 0x40000000,
131 .mask_reg = QEIC_CIMR,
132 .pri_code = 1,
133 .pri_reg = QEIC_CIPXCC,
134 },
135 [34] = {
136 .mask = 0x20000000,
137 .mask_reg = QEIC_CIMR,
138 .pri_code = 2,
139 .pri_reg = QEIC_CIPXCC,
140 },
141 [35] = {
142 .mask = 0x10000000,
143 .mask_reg = QEIC_CIMR,
144 .pri_code = 3,
145 .pri_reg = QEIC_CIPXCC,
146 },
147 [36] = {
148 .mask = 0x08000000,
149 .mask_reg = QEIC_CIMR,
150 .pri_code = 4,
151 .pri_reg = QEIC_CIPXCC,
152 },
153 [40] = {
154 .mask = 0x00800000,
155 .mask_reg = QEIC_CIMR,
156 .pri_code = 0,
157 .pri_reg = QEIC_CIPYCC,
158 },
159 [41] = {
160 .mask = 0x00400000,
161 .mask_reg = QEIC_CIMR,
162 .pri_code = 1,
163 .pri_reg = QEIC_CIPYCC,
164 },
165 [42] = {
166 .mask = 0x00200000,
167 .mask_reg = QEIC_CIMR,
168 .pri_code = 2,
169 .pri_reg = QEIC_CIPYCC,
170 },
171 [43] = {
172 .mask = 0x00100000,
173 .mask_reg = QEIC_CIMR,
174 .pri_code = 3,
175 .pri_reg = QEIC_CIPYCC,
176 },
177};
178
179static inline u32 qe_ic_read(volatile __be32 __iomem * base, unsigned int reg)
180{
181 return in_be32(base + (reg >> 2));
182}
183
184static inline void qe_ic_write(volatile __be32 __iomem * base, unsigned int reg,
185 u32 value)
186{
187 out_be32(base + (reg >> 2), value);
188}
189
190static inline struct qe_ic *qe_ic_from_irq(unsigned int virq)
191{
192 return irq_desc[virq].chip_data;
193}
194
195#define virq_to_hw(virq) ((unsigned int)irq_map[virq].hwirq)
196
197static void qe_ic_unmask_irq(unsigned int virq)
198{
199 struct qe_ic *qe_ic = qe_ic_from_irq(virq);
200 unsigned int src = virq_to_hw(virq);
201 unsigned long flags;
202 u32 temp;
203
204 spin_lock_irqsave(&qe_ic_lock, flags);
205
206 temp = qe_ic_read(qe_ic->regs, qe_ic_info[src].mask_reg);
207 qe_ic_write(qe_ic->regs, qe_ic_info[src].mask_reg,
208 temp | qe_ic_info[src].mask);
209
210 spin_unlock_irqrestore(&qe_ic_lock, flags);
211}
212
213static void qe_ic_mask_irq(unsigned int virq)
214{
215 struct qe_ic *qe_ic = qe_ic_from_irq(virq);
216 unsigned int src = virq_to_hw(virq);
217 unsigned long flags;
218 u32 temp;
219
220 spin_lock_irqsave(&qe_ic_lock, flags);
221
222 temp = qe_ic_read(qe_ic->regs, qe_ic_info[src].mask_reg);
223 qe_ic_write(qe_ic->regs, qe_ic_info[src].mask_reg,
224 temp & ~qe_ic_info[src].mask);
225
226 spin_unlock_irqrestore(&qe_ic_lock, flags);
227}
228
229static void qe_ic_mask_irq_and_ack(unsigned int virq)
230{
231 struct qe_ic *qe_ic = qe_ic_from_irq(virq);
232 unsigned int src = virq_to_hw(virq);
233 unsigned long flags;
234 u32 temp;
235
236 spin_lock_irqsave(&qe_ic_lock, flags);
237
238 temp = qe_ic_read(qe_ic->regs, qe_ic_info[src].mask_reg);
239 qe_ic_write(qe_ic->regs, qe_ic_info[src].mask_reg,
240 temp & ~qe_ic_info[src].mask);
241
242 /* There is nothing to do for ack here, ack is handled in ISR */
243
244 spin_unlock_irqrestore(&qe_ic_lock, flags);
245}
246
247static struct irq_chip qe_ic_irq_chip = {
248 .typename = " QEIC ",
249 .unmask = qe_ic_unmask_irq,
250 .mask = qe_ic_mask_irq,
251 .mask_ack = qe_ic_mask_irq_and_ack,
252};
253
254static int qe_ic_host_match(struct irq_host *h, struct device_node *node)
255{
256 struct qe_ic *qe_ic = h->host_data;
257
258 /* Exact match, unless qe_ic node is NULL */
259 return qe_ic->of_node == NULL || qe_ic->of_node == node;
260}
261
262static int qe_ic_host_map(struct irq_host *h, unsigned int virq,
263 irq_hw_number_t hw)
264{
265 struct qe_ic *qe_ic = h->host_data;
266 struct irq_chip *chip;
267
268 if (qe_ic_info[hw].mask == 0) {
269 printk(KERN_ERR "Can't map reserved IRQ \n");
270 return -EINVAL;
271 }
272 /* Default chip */
273 chip = &qe_ic->hc_irq;
274
275 set_irq_chip_data(virq, qe_ic);
276 get_irq_desc(virq)->status |= IRQ_LEVEL;
277
278 set_irq_chip_and_handler(virq, chip, handle_level_irq);
279
280 return 0;
281}
282
283static int qe_ic_host_xlate(struct irq_host *h, struct device_node *ct,
284 u32 * intspec, unsigned int intsize,
285 irq_hw_number_t * out_hwirq,
286 unsigned int *out_flags)
287{
288 *out_hwirq = intspec[0];
289 if (intsize > 1)
290 *out_flags = intspec[1];
291 else
292 *out_flags = IRQ_TYPE_NONE;
293 return 0;
294}
295
296static struct irq_host_ops qe_ic_host_ops = {
297 .match = qe_ic_host_match,
298 .map = qe_ic_host_map,
299 .xlate = qe_ic_host_xlate,
300};
301
302/* Return an interrupt vector or NO_IRQ if no interrupt is pending. */
303unsigned int qe_ic_get_low_irq(struct qe_ic *qe_ic, struct pt_regs *regs)
304{
305 int irq;
306
307 BUG_ON(qe_ic == NULL);
308
309 /* get the interrupt source vector. */
310 irq = qe_ic_read(qe_ic->regs, QEIC_CIVEC) >> 26;
311
312 if (irq == 0)
313 return NO_IRQ;
314
315 return irq_linear_revmap(qe_ic->irqhost, irq);
316}
317
318/* Return an interrupt vector or NO_IRQ if no interrupt is pending. */
319unsigned int qe_ic_get_high_irq(struct qe_ic *qe_ic, struct pt_regs *regs)
320{
321 int irq;
322
323 BUG_ON(qe_ic == NULL);
324
325 /* get the interrupt source vector. */
326 irq = qe_ic_read(qe_ic->regs, QEIC_CHIVEC) >> 26;
327
328 if (irq == 0)
329 return NO_IRQ;
330
331 return irq_linear_revmap(qe_ic->irqhost, irq);
332}
333
334/* FIXME: We mask all the QE Low interrupts while handling. We should
335 * let other interrupt come in, but BAD interrupts are generated */
336void fastcall qe_ic_cascade_low(unsigned int irq, struct irq_desc *desc,
337 struct pt_regs *regs)
338{
339 struct qe_ic *qe_ic = desc->handler_data;
340 struct irq_chip *chip = irq_desc[irq].chip;
341
342 unsigned int cascade_irq = qe_ic_get_low_irq(qe_ic, regs);
343
344 chip->mask_ack(irq);
345 if (cascade_irq != NO_IRQ)
346 generic_handle_irq(cascade_irq, regs);
347 chip->unmask(irq);
348}
349
350/* FIXME: We mask all the QE High interrupts while handling. We should
351 * let other interrupt come in, but BAD interrupts are generated */
352void fastcall qe_ic_cascade_high(unsigned int irq, struct irq_desc *desc,
353 struct pt_regs *regs)
354{
355 struct qe_ic *qe_ic = desc->handler_data;
356 struct irq_chip *chip = irq_desc[irq].chip;
357
358 unsigned int cascade_irq = qe_ic_get_high_irq(qe_ic, regs);
359
360 chip->mask_ack(irq);
361 if (cascade_irq != NO_IRQ)
362 generic_handle_irq(cascade_irq, regs);
363 chip->unmask(irq);
364}
365
366void __init qe_ic_init(struct device_node *node, unsigned int flags)
367{
368 struct qe_ic *qe_ic;
369 struct resource res;
370 u32 temp = 0, ret, high_active = 0;
371
372 qe_ic = alloc_bootmem(sizeof(struct qe_ic));
373 if (qe_ic == NULL)
374 return;
375
376 memset(qe_ic, 0, sizeof(struct qe_ic));
377 qe_ic->of_node = node ? of_node_get(node) : NULL;
378
379 qe_ic->irqhost = irq_alloc_host(IRQ_HOST_MAP_LINEAR,
380 NR_QE_IC_INTS, &qe_ic_host_ops, 0);
381 if (qe_ic->irqhost == NULL) {
382 of_node_put(node);
383 return;
384 }
385
386 ret = of_address_to_resource(node, 0, &res);
387 if (ret)
388 return;
389
390 qe_ic->regs = ioremap(res.start, res.end - res.start + 1);
391
392 qe_ic->irqhost->host_data = qe_ic;
393 qe_ic->hc_irq = qe_ic_irq_chip;
394
395 qe_ic->virq_high = irq_of_parse_and_map(node, 0);
396 qe_ic->virq_low = irq_of_parse_and_map(node, 1);
397
398 if (qe_ic->virq_low == NO_IRQ) {
399 printk(KERN_ERR "Failed to map QE_IC low IRQ\n");
400 return;
401 }
402
403 /* default priority scheme is grouped. If spread mode is */
404 /* required, configure cicr accordingly. */
405 if (flags & QE_IC_SPREADMODE_GRP_W)
406 temp |= CICR_GWCC;
407 if (flags & QE_IC_SPREADMODE_GRP_X)
408 temp |= CICR_GXCC;
409 if (flags & QE_IC_SPREADMODE_GRP_Y)
410 temp |= CICR_GYCC;
411 if (flags & QE_IC_SPREADMODE_GRP_Z)
412 temp |= CICR_GZCC;
413 if (flags & QE_IC_SPREADMODE_GRP_RISCA)
414 temp |= CICR_GRTA;
415 if (flags & QE_IC_SPREADMODE_GRP_RISCB)
416 temp |= CICR_GRTB;
417
418 /* choose destination signal for highest priority interrupt */
419 if (flags & QE_IC_HIGH_SIGNAL) {
420 temp |= (SIGNAL_HIGH << CICR_HPIT_SHIFT);
421 high_active = 1;
422 }
423
424 qe_ic_write(qe_ic->regs, QEIC_CICR, temp);
425
426 set_irq_data(qe_ic->virq_low, qe_ic);
427 set_irq_chained_handler(qe_ic->virq_low, qe_ic_cascade_low);
428
429 if (qe_ic->virq_high != NO_IRQ) {
430 set_irq_data(qe_ic->virq_high, qe_ic);
431 set_irq_chained_handler(qe_ic->virq_high, qe_ic_cascade_high);
432 }
433
434 printk("QEIC (%d IRQ sources) at %p\n", NR_QE_IC_INTS, qe_ic->regs);
435}
436
437void qe_ic_set_highest_priority(unsigned int virq, int high)
438{
439 struct qe_ic *qe_ic = qe_ic_from_irq(virq);
440 unsigned int src = virq_to_hw(virq);
441 u32 temp = 0;
442
443 temp = qe_ic_read(qe_ic->regs, QEIC_CICR);
444
445 temp &= ~CICR_HP_MASK;
446 temp |= src << CICR_HP_SHIFT;
447
448 temp &= ~CICR_HPIT_MASK;
449 temp |= (high ? SIGNAL_HIGH : SIGNAL_LOW) << CICR_HPIT_SHIFT;
450
451 qe_ic_write(qe_ic->regs, QEIC_CICR, temp);
452}
453
454/* Set Priority level within its group, from 1 to 8 */
455int qe_ic_set_priority(unsigned int virq, unsigned int priority)
456{
457 struct qe_ic *qe_ic = qe_ic_from_irq(virq);
458 unsigned int src = virq_to_hw(virq);
459 u32 temp;
460
461 if (priority > 8 || priority == 0)
462 return -EINVAL;
463 if (src > 127)
464 return -EINVAL;
465 if (qe_ic_info[src].pri_reg == 0)
466 return -EINVAL;
467
468 temp = qe_ic_read(qe_ic->regs, qe_ic_info[src].pri_reg);
469
470 if (priority < 4) {
471 temp &= ~(0x7 << (32 - priority * 3));
472 temp |= qe_ic_info[src].pri_code << (32 - priority * 3);
473 } else {
474 temp &= ~(0x7 << (24 - priority * 3));
475 temp |= qe_ic_info[src].pri_code << (24 - priority * 3);
476 }
477
478 qe_ic_write(qe_ic->regs, qe_ic_info[src].pri_reg, temp);
479
480 return 0;
481}
482
483/* Set a QE priority to use high irq, only priority 1~2 can use high irq */
484int qe_ic_set_high_priority(unsigned int virq, unsigned int priority, int high)
485{
486 struct qe_ic *qe_ic = qe_ic_from_irq(virq);
487 unsigned int src = virq_to_hw(virq);
488 u32 temp, control_reg = QEIC_CICNR, shift = 0;
489
490 if (priority > 2 || priority == 0)
491 return -EINVAL;
492
493 switch (qe_ic_info[src].pri_reg) {
494 case QEIC_CIPZCC:
495 shift = CICNR_ZCC1T_SHIFT;
496 break;
497 case QEIC_CIPWCC:
498 shift = CICNR_WCC1T_SHIFT;
499 break;
500 case QEIC_CIPYCC:
501 shift = CICNR_YCC1T_SHIFT;
502 break;
503 case QEIC_CIPXCC:
504 shift = CICNR_XCC1T_SHIFT;
505 break;
506 case QEIC_CIPRTA:
507 shift = CRICR_RTA1T_SHIFT;
508 control_reg = QEIC_CRICR;
509 break;
510 case QEIC_CIPRTB:
511 shift = CRICR_RTB1T_SHIFT;
512 control_reg = QEIC_CRICR;
513 break;
514 default:
515 return -EINVAL;
516 }
517
518 shift += (2 - priority) * 2;
519 temp = qe_ic_read(qe_ic->regs, control_reg);
520 temp &= ~(SIGNAL_MASK << shift);
521 temp |= (high ? SIGNAL_HIGH : SIGNAL_LOW) << shift;
522 qe_ic_write(qe_ic->regs, control_reg, temp);
523
524 return 0;
525}
526
527static struct sysdev_class qe_ic_sysclass = {
528 set_kset_name("qe_ic"),
529};
530
531static struct sys_device device_qe_ic = {
532 .id = 0,
533 .cls = &qe_ic_sysclass,
534};
535
536static int __init init_qe_ic_sysfs(void)
537{
538 int rc;
539
540 printk(KERN_DEBUG "Registering qe_ic with sysfs...\n");
541
542 rc = sysdev_class_register(&qe_ic_sysclass);
543 if (rc) {
544 printk(KERN_ERR "Failed registering qe_ic sys class\n");
545 return -ENODEV;
546 }
547 rc = sysdev_register(&device_qe_ic);
548 if (rc) {
549 printk(KERN_ERR "Failed registering qe_ic sys device\n");
550 return -ENODEV;
551 }
552 return 0;
553}
554
555subsys_initcall(init_qe_ic_sysfs);
diff --git a/arch/powerpc/sysdev/qe_lib/qe_ic.h b/arch/powerpc/sysdev/qe_lib/qe_ic.h
new file mode 100644
index 000000000000..9a631adb189d
--- /dev/null
+++ b/arch/powerpc/sysdev/qe_lib/qe_ic.h
@@ -0,0 +1,106 @@
1/*
2 * arch/powerpc/sysdev/qe_lib/qe_ic.h
3 *
4 * QUICC ENGINE Interrupt Controller Header
5 *
6 * Copyright (C) 2006 Freescale Semicondutor, Inc. All rights reserved.
7 *
8 * Author: Li Yang <leoli@freescale.com>
9 * Based on code from Shlomi Gridish <gridish@freescale.com>
10 *
11 * This program is free software; you can redistribute it and/or modify it
12 * under the terms of the GNU General Public License as published by the
13 * Free Software Foundation; either version 2 of the License, or (at your
14 * option) any later version.
15 */
16#ifndef _POWERPC_SYSDEV_QE_IC_H
17#define _POWERPC_SYSDEV_QE_IC_H
18
19#include <asm/qe_ic.h>
20
21#define NR_QE_IC_INTS 64
22
23/* QE IC registers offset */
24#define QEIC_CICR 0x00
25#define QEIC_CIVEC 0x04
26#define QEIC_CRIPNR 0x08
27#define QEIC_CIPNR 0x0c
28#define QEIC_CIPXCC 0x10
29#define QEIC_CIPYCC 0x14
30#define QEIC_CIPWCC 0x18
31#define QEIC_CIPZCC 0x1c
32#define QEIC_CIMR 0x20
33#define QEIC_CRIMR 0x24
34#define QEIC_CICNR 0x28
35#define QEIC_CIPRTA 0x30
36#define QEIC_CIPRTB 0x34
37#define QEIC_CRICR 0x3c
38#define QEIC_CHIVEC 0x60
39
40/* Interrupt priority registers */
41#define CIPCC_SHIFT_PRI0 29
42#define CIPCC_SHIFT_PRI1 26
43#define CIPCC_SHIFT_PRI2 23
44#define CIPCC_SHIFT_PRI3 20
45#define CIPCC_SHIFT_PRI4 13
46#define CIPCC_SHIFT_PRI5 10
47#define CIPCC_SHIFT_PRI6 7
48#define CIPCC_SHIFT_PRI7 4
49
50/* CICR priority modes */
51#define CICR_GWCC 0x00040000
52#define CICR_GXCC 0x00020000
53#define CICR_GYCC 0x00010000
54#define CICR_GZCC 0x00080000
55#define CICR_GRTA 0x00200000
56#define CICR_GRTB 0x00400000
57#define CICR_HPIT_SHIFT 8
58#define CICR_HPIT_MASK 0x00000300
59#define CICR_HP_SHIFT 24
60#define CICR_HP_MASK 0x3f000000
61
62/* CICNR */
63#define CICNR_WCC1T_SHIFT 20
64#define CICNR_ZCC1T_SHIFT 28
65#define CICNR_YCC1T_SHIFT 12
66#define CICNR_XCC1T_SHIFT 4
67
68/* CRICR */
69#define CRICR_RTA1T_SHIFT 20
70#define CRICR_RTB1T_SHIFT 28
71
72/* Signal indicator */
73#define SIGNAL_MASK 3
74#define SIGNAL_HIGH 2
75#define SIGNAL_LOW 0
76
77struct qe_ic {
78 /* Control registers offset */
79 volatile u32 __iomem *regs;
80
81 /* The remapper for this QEIC */
82 struct irq_host *irqhost;
83
84 /* The "linux" controller struct */
85 struct irq_chip hc_irq;
86
87 /* The device node of the interrupt controller */
88 struct device_node *of_node;
89
90 /* VIRQ numbers of QE high/low irqs */
91 unsigned int virq_high;
92 unsigned int virq_low;
93};
94
95/*
96 * QE interrupt controller internal structure
97 */
98struct qe_ic_info {
99 u32 mask; /* location of this source at the QIMR register. */
100 u32 mask_reg; /* Mask register offset */
101 u8 pri_code; /* for grouped interrupts sources - the interrupt
102 code as appears at the group priority register */
103 u32 pri_reg; /* Group priority register offset */
104};
105
106#endif /* _POWERPC_SYSDEV_QE_IC_H */
diff --git a/arch/powerpc/sysdev/qe_lib/qe_io.c b/arch/powerpc/sysdev/qe_lib/qe_io.c
new file mode 100644
index 000000000000..aea435970389
--- /dev/null
+++ b/arch/powerpc/sysdev/qe_lib/qe_io.c
@@ -0,0 +1,226 @@
1/*
2 * arch/powerpc/sysdev/qe_lib/qe_io.c
3 *
4 * QE Parallel I/O ports configuration routines
5 *
6 * Copyright (C) Freescale Semicondutor, Inc. 2006. All rights reserved.
7 *
8 * Author: Li Yang <LeoLi@freescale.com>
9 * Based on code from Shlomi Gridish <gridish@freescale.com>
10 *
11 * This program is free software; you can redistribute it and/or modify it
12 * under the terms of the GNU General Public License as published by the
13 * Free Software Foundation; either version 2 of the License, or (at your
14 * option) any later version.
15 */
16
17#include <linux/config.h>
18#include <linux/stddef.h>
19#include <linux/kernel.h>
20#include <linux/init.h>
21#include <linux/errno.h>
22#include <linux/module.h>
23#include <linux/ioport.h>
24
25#include <asm/io.h>
26#include <asm/prom.h>
27#include <sysdev/fsl_soc.h>
28
29#undef DEBUG
30
31#define NUM_OF_PINS 32
32
33struct port_regs {
34 __be32 cpodr; /* Open drain register */
35 __be32 cpdata; /* Data register */
36 __be32 cpdir1; /* Direction register */
37 __be32 cpdir2; /* Direction register */
38 __be32 cppar1; /* Pin assignment register */
39 __be32 cppar2; /* Pin assignment register */
40};
41
42static struct port_regs *par_io = NULL;
43static int num_par_io_ports = 0;
44
45int par_io_init(struct device_node *np)
46{
47 struct resource res;
48 int ret;
49 const u32 *num_ports;
50
51 /* Map Parallel I/O ports registers */
52 ret = of_address_to_resource(np, 0, &res);
53 if (ret)
54 return ret;
55 par_io = ioremap(res.start, res.end - res.start + 1);
56
57 num_ports = get_property(np, "num-ports", NULL);
58 if (num_ports)
59 num_par_io_ports = *num_ports;
60
61 return 0;
62}
63
64int par_io_config_pin(u8 port, u8 pin, int dir, int open_drain,
65 int assignment, int has_irq)
66{
67 u32 pin_mask1bit, pin_mask2bits, new_mask2bits, tmp_val;
68
69 if (!par_io)
70 return -1;
71
72 /* calculate pin location for single and 2 bits information */
73 pin_mask1bit = (u32) (1 << (NUM_OF_PINS - (pin + 1)));
74
75 /* Set open drain, if required */
76 tmp_val = in_be32(&par_io[port].cpodr);
77 if (open_drain)
78 out_be32(&par_io[port].cpodr, pin_mask1bit | tmp_val);
79 else
80 out_be32(&par_io[port].cpodr, ~pin_mask1bit & tmp_val);
81
82 /* define direction */
83 tmp_val = (pin > (NUM_OF_PINS / 2) - 1) ?
84 in_be32(&par_io[port].cpdir2) :
85 in_be32(&par_io[port].cpdir1);
86
87 /* get all bits mask for 2 bit per port */
88 pin_mask2bits = (u32) (0x3 << (NUM_OF_PINS -
89 (pin % (NUM_OF_PINS / 2) + 1) * 2));
90
91 /* Get the final mask we need for the right definition */
92 new_mask2bits = (u32) (dir << (NUM_OF_PINS -
93 (pin % (NUM_OF_PINS / 2) + 1) * 2));
94
95 /* clear and set 2 bits mask */
96 if (pin > (NUM_OF_PINS / 2) - 1) {
97 out_be32(&par_io[port].cpdir2,
98 ~pin_mask2bits & tmp_val);
99 tmp_val &= ~pin_mask2bits;
100 out_be32(&par_io[port].cpdir2, new_mask2bits | tmp_val);
101 } else {
102 out_be32(&par_io[port].cpdir1,
103 ~pin_mask2bits & tmp_val);
104 tmp_val &= ~pin_mask2bits;
105 out_be32(&par_io[port].cpdir1, new_mask2bits | tmp_val);
106 }
107 /* define pin assignment */
108 tmp_val = (pin > (NUM_OF_PINS / 2) - 1) ?
109 in_be32(&par_io[port].cppar2) :
110 in_be32(&par_io[port].cppar1);
111
112 new_mask2bits = (u32) (assignment << (NUM_OF_PINS -
113 (pin % (NUM_OF_PINS / 2) + 1) * 2));
114 /* clear and set 2 bits mask */
115 if (pin > (NUM_OF_PINS / 2) - 1) {
116 out_be32(&par_io[port].cppar2,
117 ~pin_mask2bits & tmp_val);
118 tmp_val &= ~pin_mask2bits;
119 out_be32(&par_io[port].cppar2, new_mask2bits | tmp_val);
120 } else {
121 out_be32(&par_io[port].cppar1,
122 ~pin_mask2bits & tmp_val);
123 tmp_val &= ~pin_mask2bits;
124 out_be32(&par_io[port].cppar1, new_mask2bits | tmp_val);
125 }
126
127 return 0;
128}
129EXPORT_SYMBOL(par_io_config_pin);
130
131int par_io_data_set(u8 port, u8 pin, u8 val)
132{
133 u32 pin_mask, tmp_val;
134
135 if (port >= num_par_io_ports)
136 return -EINVAL;
137 if (pin >= NUM_OF_PINS)
138 return -EINVAL;
139 /* calculate pin location */
140 pin_mask = (u32) (1 << (NUM_OF_PINS - 1 - pin));
141
142 tmp_val = in_be32(&par_io[port].cpdata);
143
144 if (val == 0) /* clear */
145 out_be32(&par_io[port].cpdata, ~pin_mask & tmp_val);
146 else /* set */
147 out_be32(&par_io[port].cpdata, pin_mask | tmp_val);
148
149 return 0;
150}
151EXPORT_SYMBOL(par_io_data_set);
152
153int par_io_of_config(struct device_node *np)
154{
155 struct device_node *pio;
156 const phandle *ph;
157 int pio_map_len;
158 const unsigned int *pio_map;
159
160 if (par_io == NULL) {
161 printk(KERN_ERR "par_io not initialized \n");
162 return -1;
163 }
164
165 ph = get_property(np, "pio-handle", NULL);
166 if (ph == 0) {
167 printk(KERN_ERR "pio-handle not available \n");
168 return -1;
169 }
170
171 pio = of_find_node_by_phandle(*ph);
172
173 pio_map = get_property(pio, "pio-map", &pio_map_len);
174 if (pio_map == NULL) {
175 printk(KERN_ERR "pio-map is not set! \n");
176 return -1;
177 }
178 pio_map_len /= sizeof(unsigned int);
179 if ((pio_map_len % 6) != 0) {
180 printk(KERN_ERR "pio-map format wrong! \n");
181 return -1;
182 }
183
184 while (pio_map_len > 0) {
185 par_io_config_pin((u8) pio_map[0], (u8) pio_map[1],
186 (int) pio_map[2], (int) pio_map[3],
187 (int) pio_map[4], (int) pio_map[5]);
188 pio_map += 6;
189 pio_map_len -= 6;
190 }
191 of_node_put(pio);
192 return 0;
193}
194EXPORT_SYMBOL(par_io_of_config);
195
196#ifdef DEBUG
197static void dump_par_io(void)
198{
199 int i;
200
201 printk(KERN_INFO "PAR IO registars:\n");
202 printk(KERN_INFO "Base address: 0x%08x\n", (u32) par_io);
203 for (i = 0; i < num_par_io_ports; i++) {
204 printk(KERN_INFO "cpodr[%d] : addr - 0x%08x, val - 0x%08x\n",
205 i, (u32) & par_io[i].cpodr,
206 in_be32(&par_io[i].cpodr));
207 printk(KERN_INFO "cpdata[%d]: addr - 0x%08x, val - 0x%08x\n",
208 i, (u32) & par_io[i].cpdata,
209 in_be32(&par_io[i].cpdata));
210 printk(KERN_INFO "cpdir1[%d]: addr - 0x%08x, val - 0x%08x\n",
211 i, (u32) & par_io[i].cpdir1,
212 in_be32(&par_io[i].cpdir1));
213 printk(KERN_INFO "cpdir2[%d]: addr - 0x%08x, val - 0x%08x\n",
214 i, (u32) & par_io[i].cpdir2,
215 in_be32(&par_io[i].cpdir2));
216 printk(KERN_INFO "cppar1[%d]: addr - 0x%08x, val - 0x%08x\n",
217 i, (u32) & par_io[i].cppar1,
218 in_be32(&par_io[i].cppar1));
219 printk(KERN_INFO "cppar2[%d]: addr - 0x%08x, val - 0x%08x\n",
220 i, (u32) & par_io[i].cppar2,
221 in_be32(&par_io[i].cppar2));
222 }
223
224}
225EXPORT_SYMBOL(dump_par_io);
226#endif /* DEBUG */
diff --git a/arch/powerpc/sysdev/qe_lib/ucc.c b/arch/powerpc/sysdev/qe_lib/ucc.c
new file mode 100644
index 000000000000..916c9e5df57f
--- /dev/null
+++ b/arch/powerpc/sysdev/qe_lib/ucc.c
@@ -0,0 +1,251 @@
1/*
2 * arch/powerpc/sysdev/qe_lib/ucc.c
3 *
4 * QE UCC API Set - UCC specific routines implementations.
5 *
6 * Copyright (C) 2006 Freescale Semicondutor, Inc. All rights reserved.
7 *
8 * Authors: Shlomi Gridish <gridish@freescale.com>
9 * Li Yang <leoli@freescale.com>
10 *
11 * This program is free software; you can redistribute it and/or modify it
12 * under the terms of the GNU General Public License as published by the
13 * Free Software Foundation; either version 2 of the License, or (at your
14 * option) any later version.
15 */
16#include <linux/kernel.h>
17#include <linux/init.h>
18#include <linux/errno.h>
19#include <linux/slab.h>
20#include <linux/stddef.h>
21
22#include <asm/irq.h>
23#include <asm/io.h>
24#include <asm/immap_qe.h>
25#include <asm/qe.h>
26#include <asm/ucc.h>
27
28static DEFINE_SPINLOCK(ucc_lock);
29
30int ucc_set_qe_mux_mii_mng(int ucc_num)
31{
32 unsigned long flags;
33
34 spin_lock_irqsave(&ucc_lock, flags);
35 out_be32(&qe_immr->qmx.cmxgcr,
36 ((in_be32(&qe_immr->qmx.cmxgcr) &
37 ~QE_CMXGCR_MII_ENET_MNG) |
38 (ucc_num << QE_CMXGCR_MII_ENET_MNG_SHIFT)));
39 spin_unlock_irqrestore(&ucc_lock, flags);
40
41 return 0;
42}
43
44int ucc_set_type(int ucc_num, struct ucc_common *regs,
45 enum ucc_speed_type speed)
46{
47 u8 guemr = 0;
48
49 /* check if the UCC number is in range. */
50 if ((ucc_num > UCC_MAX_NUM - 1) || (ucc_num < 0))
51 return -EINVAL;
52
53 guemr = regs->guemr;
54 guemr &= ~(UCC_GUEMR_MODE_MASK_RX | UCC_GUEMR_MODE_MASK_TX);
55 switch (speed) {
56 case UCC_SPEED_TYPE_SLOW:
57 guemr |= (UCC_GUEMR_MODE_SLOW_RX | UCC_GUEMR_MODE_SLOW_TX);
58 break;
59 case UCC_SPEED_TYPE_FAST:
60 guemr |= (UCC_GUEMR_MODE_FAST_RX | UCC_GUEMR_MODE_FAST_TX);
61 break;
62 default:
63 return -EINVAL;
64 }
65 regs->guemr = guemr;
66
67 return 0;
68}
69
70int ucc_init_guemr(struct ucc_common *regs)
71{
72 u8 guemr = 0;
73
74 if (!regs)
75 return -EINVAL;
76
77 /* Set bit 3 (which is reserved in the GUEMR register) to 1 */
78 guemr = UCC_GUEMR_SET_RESERVED3;
79
80 regs->guemr = guemr;
81
82 return 0;
83}
84
85static void get_cmxucr_reg(int ucc_num, volatile u32 ** p_cmxucr, u8 * reg_num,
86 u8 * shift)
87{
88 switch (ucc_num) {
89 case 0: *p_cmxucr = &(qe_immr->qmx.cmxucr1);
90 *reg_num = 1;
91 *shift = 16;
92 break;
93 case 2: *p_cmxucr = &(qe_immr->qmx.cmxucr1);
94 *reg_num = 1;
95 *shift = 0;
96 break;
97 case 4: *p_cmxucr = &(qe_immr->qmx.cmxucr2);
98 *reg_num = 2;
99 *shift = 16;
100 break;
101 case 6: *p_cmxucr = &(qe_immr->qmx.cmxucr2);
102 *reg_num = 2;
103 *shift = 0;
104 break;
105 case 1: *p_cmxucr = &(qe_immr->qmx.cmxucr3);
106 *reg_num = 3;
107 *shift = 16;
108 break;
109 case 3: *p_cmxucr = &(qe_immr->qmx.cmxucr3);
110 *reg_num = 3;
111 *shift = 0;
112 break;
113 case 5: *p_cmxucr = &(qe_immr->qmx.cmxucr4);
114 *reg_num = 4;
115 *shift = 16;
116 break;
117 case 7: *p_cmxucr = &(qe_immr->qmx.cmxucr4);
118 *reg_num = 4;
119 *shift = 0;
120 break;
121 default:
122 break;
123 }
124}
125
126int ucc_mux_set_grant_tsa_bkpt(int ucc_num, int set, u32 mask)
127{
128 volatile u32 *p_cmxucr;
129 u8 reg_num;
130 u8 shift;
131
132 /* check if the UCC number is in range. */
133 if ((ucc_num > UCC_MAX_NUM - 1) || (ucc_num < 0))
134 return -EINVAL;
135
136 get_cmxucr_reg(ucc_num, &p_cmxucr, &reg_num, &shift);
137
138 if (set)
139 out_be32(p_cmxucr, in_be32(p_cmxucr) | (mask << shift));
140 else
141 out_be32(p_cmxucr, in_be32(p_cmxucr) & ~(mask << shift));
142
143 return 0;
144}
145
146int ucc_set_qe_mux_rxtx(int ucc_num, enum qe_clock clock, enum comm_dir mode)
147{
148 volatile u32 *p_cmxucr;
149 u8 reg_num;
150 u8 shift;
151 u32 clock_bits;
152 u32 clock_mask;
153 int source = -1;
154
155 /* check if the UCC number is in range. */
156 if ((ucc_num > UCC_MAX_NUM - 1) || (ucc_num < 0))
157 return -EINVAL;
158
159 if (!((mode == COMM_DIR_RX) || (mode == COMM_DIR_TX))) {
160 printk(KERN_ERR
161 "ucc_set_qe_mux_rxtx: bad comm mode type passed.");
162 return -EINVAL;
163 }
164
165 get_cmxucr_reg(ucc_num, &p_cmxucr, &reg_num, &shift);
166
167 switch (reg_num) {
168 case 1:
169 switch (clock) {
170 case QE_BRG1: source = 1; break;
171 case QE_BRG2: source = 2; break;
172 case QE_BRG7: source = 3; break;
173 case QE_BRG8: source = 4; break;
174 case QE_CLK9: source = 5; break;
175 case QE_CLK10: source = 6; break;
176 case QE_CLK11: source = 7; break;
177 case QE_CLK12: source = 8; break;
178 case QE_CLK15: source = 9; break;
179 case QE_CLK16: source = 10; break;
180 default: source = -1; break;
181 }
182 break;
183 case 2:
184 switch (clock) {
185 case QE_BRG5: source = 1; break;
186 case QE_BRG6: source = 2; break;
187 case QE_BRG7: source = 3; break;
188 case QE_BRG8: source = 4; break;
189 case QE_CLK13: source = 5; break;
190 case QE_CLK14: source = 6; break;
191 case QE_CLK19: source = 7; break;
192 case QE_CLK20: source = 8; break;
193 case QE_CLK15: source = 9; break;
194 case QE_CLK16: source = 10; break;
195 default: source = -1; break;
196 }
197 break;
198 case 3:
199 switch (clock) {
200 case QE_BRG9: source = 1; break;
201 case QE_BRG10: source = 2; break;
202 case QE_BRG15: source = 3; break;
203 case QE_BRG16: source = 4; break;
204 case QE_CLK3: source = 5; break;
205 case QE_CLK4: source = 6; break;
206 case QE_CLK17: source = 7; break;
207 case QE_CLK18: source = 8; break;
208 case QE_CLK7: source = 9; break;
209 case QE_CLK8: source = 10; break;
210 default: source = -1; break;
211 }
212 break;
213 case 4:
214 switch (clock) {
215 case QE_BRG13: source = 1; break;
216 case QE_BRG14: source = 2; break;
217 case QE_BRG15: source = 3; break;
218 case QE_BRG16: source = 4; break;
219 case QE_CLK5: source = 5; break;
220 case QE_CLK6: source = 6; break;
221 case QE_CLK21: source = 7; break;
222 case QE_CLK22: source = 8; break;
223 case QE_CLK7: source = 9; break;
224 case QE_CLK8: source = 10; break;
225 default: source = -1; break;
226 }
227 break;
228 default:
229 source = -1;
230 break;
231 }
232
233 if (source == -1) {
234 printk(KERN_ERR
235 "ucc_set_qe_mux_rxtx: Bad combination of clock and UCC.");
236 return -ENOENT;
237 }
238
239 clock_bits = (u32) source;
240 clock_mask = QE_CMXUCR_TX_CLK_SRC_MASK;
241 if (mode == COMM_DIR_RX) {
242 clock_bits <<= 4; /* Rx field is 4 bits to left of Tx field */
243 clock_mask <<= 4; /* Rx field is 4 bits to left of Tx field */
244 }
245 clock_bits <<= shift;
246 clock_mask <<= shift;
247
248 out_be32(p_cmxucr, (in_be32(p_cmxucr) & ~clock_mask) | clock_bits);
249
250 return 0;
251}
diff --git a/arch/powerpc/sysdev/qe_lib/ucc_fast.c b/arch/powerpc/sysdev/qe_lib/ucc_fast.c
new file mode 100644
index 000000000000..c2be7348fcbd
--- /dev/null
+++ b/arch/powerpc/sysdev/qe_lib/ucc_fast.c
@@ -0,0 +1,396 @@
1/*
2 * arch/powerpc/sysdev/qe_lib/ucc_fast.c
3 *
4 * QE UCC Fast API Set - UCC Fast specific routines implementations.
5 *
6 * Copyright (C) 2006 Freescale Semicondutor, Inc. All rights reserved.
7 *
8 * Authors: Shlomi Gridish <gridish@freescale.com>
9 * Li Yang <leoli@freescale.com>
10 *
11 * This program is free software; you can redistribute it and/or modify it
12 * under the terms of the GNU General Public License as published by the
13 * Free Software Foundation; either version 2 of the License, or (at your
14 * option) any later version.
15 */
16#include <linux/kernel.h>
17#include <linux/init.h>
18#include <linux/errno.h>
19#include <linux/slab.h>
20#include <linux/stddef.h>
21#include <linux/interrupt.h>
22
23#include <asm/io.h>
24#include <asm/immap_qe.h>
25#include <asm/qe.h>
26
27#include <asm/ucc.h>
28#include <asm/ucc_fast.h>
29
30#define uccf_printk(level, format, arg...) \
31 printk(level format "\n", ## arg)
32
33#define uccf_dbg(format, arg...) \
34 uccf_printk(KERN_DEBUG , format , ## arg)
35#define uccf_err(format, arg...) \
36 uccf_printk(KERN_ERR , format , ## arg)
37#define uccf_info(format, arg...) \
38 uccf_printk(KERN_INFO , format , ## arg)
39#define uccf_warn(format, arg...) \
40 uccf_printk(KERN_WARNING , format , ## arg)
41
42#ifdef UCCF_VERBOSE_DEBUG
43#define uccf_vdbg uccf_dbg
44#else
45#define uccf_vdbg(fmt, args...) do { } while (0)
46#endif /* UCCF_VERBOSE_DEBUG */
47
48void ucc_fast_dump_regs(struct ucc_fast_private * uccf)
49{
50 uccf_info("UCC%d Fast registers:", uccf->uf_info->ucc_num);
51 uccf_info("Base address: 0x%08x", (u32) uccf->uf_regs);
52
53 uccf_info("gumr : addr - 0x%08x, val - 0x%08x",
54 (u32) & uccf->uf_regs->gumr, in_be32(&uccf->uf_regs->gumr));
55 uccf_info("upsmr : addr - 0x%08x, val - 0x%08x",
56 (u32) & uccf->uf_regs->upsmr, in_be32(&uccf->uf_regs->upsmr));
57 uccf_info("utodr : addr - 0x%08x, val - 0x%04x",
58 (u32) & uccf->uf_regs->utodr, in_be16(&uccf->uf_regs->utodr));
59 uccf_info("udsr : addr - 0x%08x, val - 0x%04x",
60 (u32) & uccf->uf_regs->udsr, in_be16(&uccf->uf_regs->udsr));
61 uccf_info("ucce : addr - 0x%08x, val - 0x%08x",
62 (u32) & uccf->uf_regs->ucce, in_be32(&uccf->uf_regs->ucce));
63 uccf_info("uccm : addr - 0x%08x, val - 0x%08x",
64 (u32) & uccf->uf_regs->uccm, in_be32(&uccf->uf_regs->uccm));
65 uccf_info("uccs : addr - 0x%08x, val - 0x%02x",
66 (u32) & uccf->uf_regs->uccs, uccf->uf_regs->uccs);
67 uccf_info("urfb : addr - 0x%08x, val - 0x%08x",
68 (u32) & uccf->uf_regs->urfb, in_be32(&uccf->uf_regs->urfb));
69 uccf_info("urfs : addr - 0x%08x, val - 0x%04x",
70 (u32) & uccf->uf_regs->urfs, in_be16(&uccf->uf_regs->urfs));
71 uccf_info("urfet : addr - 0x%08x, val - 0x%04x",
72 (u32) & uccf->uf_regs->urfet, in_be16(&uccf->uf_regs->urfet));
73 uccf_info("urfset: addr - 0x%08x, val - 0x%04x",
74 (u32) & uccf->uf_regs->urfset,
75 in_be16(&uccf->uf_regs->urfset));
76 uccf_info("utfb : addr - 0x%08x, val - 0x%08x",
77 (u32) & uccf->uf_regs->utfb, in_be32(&uccf->uf_regs->utfb));
78 uccf_info("utfs : addr - 0x%08x, val - 0x%04x",
79 (u32) & uccf->uf_regs->utfs, in_be16(&uccf->uf_regs->utfs));
80 uccf_info("utfet : addr - 0x%08x, val - 0x%04x",
81 (u32) & uccf->uf_regs->utfet, in_be16(&uccf->uf_regs->utfet));
82 uccf_info("utftt : addr - 0x%08x, val - 0x%04x",
83 (u32) & uccf->uf_regs->utftt, in_be16(&uccf->uf_regs->utftt));
84 uccf_info("utpt : addr - 0x%08x, val - 0x%04x",
85 (u32) & uccf->uf_regs->utpt, in_be16(&uccf->uf_regs->utpt));
86 uccf_info("urtry : addr - 0x%08x, val - 0x%08x",
87 (u32) & uccf->uf_regs->urtry, in_be32(&uccf->uf_regs->urtry));
88 uccf_info("guemr : addr - 0x%08x, val - 0x%02x",
89 (u32) & uccf->uf_regs->guemr, uccf->uf_regs->guemr);
90}
91
92u32 ucc_fast_get_qe_cr_subblock(int uccf_num)
93{
94 switch (uccf_num) {
95 case 0: return QE_CR_SUBBLOCK_UCCFAST1;
96 case 1: return QE_CR_SUBBLOCK_UCCFAST2;
97 case 2: return QE_CR_SUBBLOCK_UCCFAST3;
98 case 3: return QE_CR_SUBBLOCK_UCCFAST4;
99 case 4: return QE_CR_SUBBLOCK_UCCFAST5;
100 case 5: return QE_CR_SUBBLOCK_UCCFAST6;
101 case 6: return QE_CR_SUBBLOCK_UCCFAST7;
102 case 7: return QE_CR_SUBBLOCK_UCCFAST8;
103 default: return QE_CR_SUBBLOCK_INVALID;
104 }
105}
106
107void ucc_fast_transmit_on_demand(struct ucc_fast_private * uccf)
108{
109 out_be16(&uccf->uf_regs->utodr, UCC_FAST_TOD);
110}
111
112void ucc_fast_enable(struct ucc_fast_private * uccf, enum comm_dir mode)
113{
114 struct ucc_fast *uf_regs;
115 u32 gumr;
116
117 uf_regs = uccf->uf_regs;
118
119 /* Enable reception and/or transmission on this UCC. */
120 gumr = in_be32(&uf_regs->gumr);
121 if (mode & COMM_DIR_TX) {
122 gumr |= UCC_FAST_GUMR_ENT;
123 uccf->enabled_tx = 1;
124 }
125 if (mode & COMM_DIR_RX) {
126 gumr |= UCC_FAST_GUMR_ENR;
127 uccf->enabled_rx = 1;
128 }
129 out_be32(&uf_regs->gumr, gumr);
130}
131
132void ucc_fast_disable(struct ucc_fast_private * uccf, enum comm_dir mode)
133{
134 struct ucc_fast *uf_regs;
135 u32 gumr;
136
137 uf_regs = uccf->uf_regs;
138
139 /* Disable reception and/or transmission on this UCC. */
140 gumr = in_be32(&uf_regs->gumr);
141 if (mode & COMM_DIR_TX) {
142 gumr &= ~UCC_FAST_GUMR_ENT;
143 uccf->enabled_tx = 0;
144 }
145 if (mode & COMM_DIR_RX) {
146 gumr &= ~UCC_FAST_GUMR_ENR;
147 uccf->enabled_rx = 0;
148 }
149 out_be32(&uf_regs->gumr, gumr);
150}
151
152int ucc_fast_init(struct ucc_fast_info * uf_info, struct ucc_fast_private ** uccf_ret)
153{
154 struct ucc_fast_private *uccf;
155 struct ucc_fast *uf_regs;
156 u32 gumr = 0;
157 int ret;
158
159 uccf_vdbg("%s: IN", __FUNCTION__);
160
161 if (!uf_info)
162 return -EINVAL;
163
164 /* check if the UCC port number is in range. */
165 if ((uf_info->ucc_num < 0) || (uf_info->ucc_num > UCC_MAX_NUM - 1)) {
166 uccf_err("ucc_fast_init: Illagal UCC number!");
167 return -EINVAL;
168 }
169
170 /* Check that 'max_rx_buf_length' is properly aligned (4). */
171 if (uf_info->max_rx_buf_length & (UCC_FAST_MRBLR_ALIGNMENT - 1)) {
172 uccf_err("ucc_fast_init: max_rx_buf_length not aligned.");
173 return -EINVAL;
174 }
175
176 /* Validate Virtual Fifo register values */
177 if (uf_info->urfs < UCC_FAST_URFS_MIN_VAL) {
178 uccf_err
179 ("ucc_fast_init: Virtual Fifo register urfs too small.");
180 return -EINVAL;
181 }
182
183 if (uf_info->urfs & (UCC_FAST_VIRT_FIFO_REGS_ALIGNMENT - 1)) {
184 uccf_err
185 ("ucc_fast_init: Virtual Fifo register urfs not aligned.");
186 return -EINVAL;
187 }
188
189 if (uf_info->urfet & (UCC_FAST_VIRT_FIFO_REGS_ALIGNMENT - 1)) {
190 uccf_err
191 ("ucc_fast_init: Virtual Fifo register urfet not aligned.");
192 return -EINVAL;
193 }
194
195 if (uf_info->urfset & (UCC_FAST_VIRT_FIFO_REGS_ALIGNMENT - 1)) {
196 uccf_err
197 ("ucc_fast_init: Virtual Fifo register urfset not aligned.");
198 return -EINVAL;
199 }
200
201 if (uf_info->utfs & (UCC_FAST_VIRT_FIFO_REGS_ALIGNMENT - 1)) {
202 uccf_err
203 ("ucc_fast_init: Virtual Fifo register utfs not aligned.");
204 return -EINVAL;
205 }
206
207 if (uf_info->utfet & (UCC_FAST_VIRT_FIFO_REGS_ALIGNMENT - 1)) {
208 uccf_err
209 ("ucc_fast_init: Virtual Fifo register utfet not aligned.");
210 return -EINVAL;
211 }
212
213 if (uf_info->utftt & (UCC_FAST_VIRT_FIFO_REGS_ALIGNMENT - 1)) {
214 uccf_err
215 ("ucc_fast_init: Virtual Fifo register utftt not aligned.");
216 return -EINVAL;
217 }
218
219 uccf = (struct ucc_fast_private *)
220 kmalloc(sizeof(struct ucc_fast_private), GFP_KERNEL);
221 if (!uccf) {
222 uccf_err
223 ("ucc_fast_init: No memory for UCC slow data structure!");
224 return -ENOMEM;
225 }
226 memset(uccf, 0, sizeof(struct ucc_fast_private));
227
228 /* Fill fast UCC structure */
229 uccf->uf_info = uf_info;
230 /* Set the PHY base address */
231 uccf->uf_regs =
232 (struct ucc_fast *) ioremap(uf_info->regs, sizeof(struct ucc_fast));
233 if (uccf->uf_regs == NULL) {
234 uccf_err
235 ("ucc_fast_init: No memory map for UCC slow controller!");
236 return -ENOMEM;
237 }
238
239 uccf->enabled_tx = 0;
240 uccf->enabled_rx = 0;
241 uccf->stopped_tx = 0;
242 uccf->stopped_rx = 0;
243 uf_regs = uccf->uf_regs;
244 uccf->p_ucce = (u32 *) & (uf_regs->ucce);
245 uccf->p_uccm = (u32 *) & (uf_regs->uccm);
246#ifdef STATISTICS
247 uccf->tx_frames = 0;
248 uccf->rx_frames = 0;
249 uccf->rx_discarded = 0;
250#endif /* STATISTICS */
251
252 /* Init Guemr register */
253 if ((ret = ucc_init_guemr((struct ucc_common *) (uf_regs)))) {
254 uccf_err("ucc_fast_init: Could not init the guemr register.");
255 ucc_fast_free(uccf);
256 return ret;
257 }
258
259 /* Set UCC to fast type */
260 if ((ret = ucc_set_type(uf_info->ucc_num,
261 (struct ucc_common *) (uf_regs),
262 UCC_SPEED_TYPE_FAST))) {
263 uccf_err("ucc_fast_init: Could not set type to fast.");
264 ucc_fast_free(uccf);
265 return ret;
266 }
267
268 uccf->mrblr = uf_info->max_rx_buf_length;
269
270 /* Set GUMR */
271 /* For more details see the hardware spec. */
272 /* gumr starts as zero. */
273 if (uf_info->tci)
274 gumr |= UCC_FAST_GUMR_TCI;
275 gumr |= uf_info->ttx_trx;
276 if (uf_info->cdp)
277 gumr |= UCC_FAST_GUMR_CDP;
278 if (uf_info->ctsp)
279 gumr |= UCC_FAST_GUMR_CTSP;
280 if (uf_info->cds)
281 gumr |= UCC_FAST_GUMR_CDS;
282 if (uf_info->ctss)
283 gumr |= UCC_FAST_GUMR_CTSS;
284 if (uf_info->txsy)
285 gumr |= UCC_FAST_GUMR_TXSY;
286 if (uf_info->rsyn)
287 gumr |= UCC_FAST_GUMR_RSYN;
288 gumr |= uf_info->synl;
289 if (uf_info->rtsm)
290 gumr |= UCC_FAST_GUMR_RTSM;
291 gumr |= uf_info->renc;
292 if (uf_info->revd)
293 gumr |= UCC_FAST_GUMR_REVD;
294 gumr |= uf_info->tenc;
295 gumr |= uf_info->tcrc;
296 gumr |= uf_info->mode;
297 out_be32(&uf_regs->gumr, gumr);
298
299 /* Allocate memory for Tx Virtual Fifo */
300 uccf->ucc_fast_tx_virtual_fifo_base_offset =
301 qe_muram_alloc(uf_info->utfs, UCC_FAST_VIRT_FIFO_REGS_ALIGNMENT);
302 if (IS_MURAM_ERR(uccf->ucc_fast_tx_virtual_fifo_base_offset)) {
303 uccf_err
304 ("ucc_fast_init: Can not allocate MURAM memory for "
305 "struct ucc_fastx_virtual_fifo_base_offset.");
306 uccf->ucc_fast_tx_virtual_fifo_base_offset = 0;
307 ucc_fast_free(uccf);
308 return -ENOMEM;
309 }
310
311 /* Allocate memory for Rx Virtual Fifo */
312 uccf->ucc_fast_rx_virtual_fifo_base_offset =
313 qe_muram_alloc(uf_info->urfs +
314 (u32)
315 UCC_FAST_RECEIVE_VIRTUAL_FIFO_SIZE_FUDGE_FACTOR,
316 UCC_FAST_VIRT_FIFO_REGS_ALIGNMENT);
317 if (IS_MURAM_ERR(uccf->ucc_fast_rx_virtual_fifo_base_offset)) {
318 uccf_err
319 ("ucc_fast_init: Can not allocate MURAM memory for "
320 "ucc_fast_rx_virtual_fifo_base_offset.");
321 uccf->ucc_fast_rx_virtual_fifo_base_offset = 0;
322 ucc_fast_free(uccf);
323 return -ENOMEM;
324 }
325
326 /* Set Virtual Fifo registers */
327 out_be16(&uf_regs->urfs, uf_info->urfs);
328 out_be16(&uf_regs->urfet, uf_info->urfet);
329 out_be16(&uf_regs->urfset, uf_info->urfset);
330 out_be16(&uf_regs->utfs, uf_info->utfs);
331 out_be16(&uf_regs->utfet, uf_info->utfet);
332 out_be16(&uf_regs->utftt, uf_info->utftt);
333 /* utfb, urfb are offsets from MURAM base */
334 out_be32(&uf_regs->utfb, uccf->ucc_fast_tx_virtual_fifo_base_offset);
335 out_be32(&uf_regs->urfb, uccf->ucc_fast_rx_virtual_fifo_base_offset);
336
337 /* Mux clocking */
338 /* Grant Support */
339 ucc_set_qe_mux_grant(uf_info->ucc_num, uf_info->grant_support);
340 /* Breakpoint Support */
341 ucc_set_qe_mux_bkpt(uf_info->ucc_num, uf_info->brkpt_support);
342 /* Set Tsa or NMSI mode. */
343 ucc_set_qe_mux_tsa(uf_info->ucc_num, uf_info->tsa);
344 /* If NMSI (not Tsa), set Tx and Rx clock. */
345 if (!uf_info->tsa) {
346 /* Rx clock routing */
347 if (uf_info->rx_clock != QE_CLK_NONE) {
348 if (ucc_set_qe_mux_rxtx
349 (uf_info->ucc_num, uf_info->rx_clock,
350 COMM_DIR_RX)) {
351 uccf_err
352 ("ucc_fast_init: Illegal value for parameter 'RxClock'.");
353 ucc_fast_free(uccf);
354 return -EINVAL;
355 }
356 }
357 /* Tx clock routing */
358 if (uf_info->tx_clock != QE_CLK_NONE) {
359 if (ucc_set_qe_mux_rxtx
360 (uf_info->ucc_num, uf_info->tx_clock,
361 COMM_DIR_TX)) {
362 uccf_err
363 ("ucc_fast_init: Illegal value for parameter 'TxClock'.");
364 ucc_fast_free(uccf);
365 return -EINVAL;
366 }
367 }
368 }
369
370 /* Set interrupt mask register at UCC level. */
371 out_be32(&uf_regs->uccm, uf_info->uccm_mask);
372
373 /* First, clear anything pending at UCC level,
374 * otherwise, old garbage may come through
375 * as soon as the dam is opened
376 * Writing '1' clears
377 */
378 out_be32(&uf_regs->ucce, 0xffffffff);
379
380 *uccf_ret = uccf;
381 return 0;
382}
383
384void ucc_fast_free(struct ucc_fast_private * uccf)
385{
386 if (!uccf)
387 return;
388
389 if (uccf->ucc_fast_tx_virtual_fifo_base_offset)
390 qe_muram_free(uccf->ucc_fast_tx_virtual_fifo_base_offset);
391
392 if (uccf->ucc_fast_rx_virtual_fifo_base_offset)
393 qe_muram_free(uccf->ucc_fast_rx_virtual_fifo_base_offset);
394
395 kfree(uccf);
396}
diff --git a/arch/powerpc/sysdev/qe_lib/ucc_slow.c b/arch/powerpc/sysdev/qe_lib/ucc_slow.c
new file mode 100644
index 000000000000..1fb88ef7cf06
--- /dev/null
+++ b/arch/powerpc/sysdev/qe_lib/ucc_slow.c
@@ -0,0 +1,404 @@
1/*
2 * Copyright (C) 2006 Freescale Semicondutor, Inc. All rights reserved.
3 *
4 * Authors: Shlomi Gridish <gridish@freescale.com>
5 * Li Yang <leoli@freescale.com>
6 *
7 * Description:
8 * QE UCC Slow API Set - UCC Slow specific routines implementations.
9 *
10 * This program is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU General Public License as published by the
12 * Free Software Foundation; either version 2 of the License, or (at your
13 * option) any later version.
14 */
15#include <linux/kernel.h>
16#include <linux/init.h>
17#include <linux/errno.h>
18#include <linux/slab.h>
19#include <linux/stddef.h>
20#include <linux/interrupt.h>
21
22#include <asm/irq.h>
23#include <asm/io.h>
24#include <asm/immap_qe.h>
25#include <asm/qe.h>
26
27#include <asm/ucc.h>
28#include <asm/ucc_slow.h>
29
30#define uccs_printk(level, format, arg...) \
31 printk(level format "\n", ## arg)
32
33#define uccs_dbg(format, arg...) \
34 uccs_printk(KERN_DEBUG , format , ## arg)
35#define uccs_err(format, arg...) \
36 uccs_printk(KERN_ERR , format , ## arg)
37#define uccs_info(format, arg...) \
38 uccs_printk(KERN_INFO , format , ## arg)
39#define uccs_warn(format, arg...) \
40 uccs_printk(KERN_WARNING , format , ## arg)
41
42#ifdef UCCS_VERBOSE_DEBUG
43#define uccs_vdbg uccs_dbg
44#else
45#define uccs_vdbg(fmt, args...) do { } while (0)
46#endif /* UCCS_VERBOSE_DEBUG */
47
48u32 ucc_slow_get_qe_cr_subblock(int uccs_num)
49{
50 switch (uccs_num) {
51 case 0: return QE_CR_SUBBLOCK_UCCSLOW1;
52 case 1: return QE_CR_SUBBLOCK_UCCSLOW2;
53 case 2: return QE_CR_SUBBLOCK_UCCSLOW3;
54 case 3: return QE_CR_SUBBLOCK_UCCSLOW4;
55 case 4: return QE_CR_SUBBLOCK_UCCSLOW5;
56 case 5: return QE_CR_SUBBLOCK_UCCSLOW6;
57 case 6: return QE_CR_SUBBLOCK_UCCSLOW7;
58 case 7: return QE_CR_SUBBLOCK_UCCSLOW8;
59 default: return QE_CR_SUBBLOCK_INVALID;
60 }
61}
62
63void ucc_slow_poll_transmitter_now(struct ucc_slow_private * uccs)
64{
65 out_be16(&uccs->us_regs->utodr, UCC_SLOW_TOD);
66}
67
68void ucc_slow_graceful_stop_tx(struct ucc_slow_private * uccs)
69{
70 struct ucc_slow_info *us_info = uccs->us_info;
71 u32 id;
72
73 id = ucc_slow_get_qe_cr_subblock(us_info->ucc_num);
74 qe_issue_cmd(QE_GRACEFUL_STOP_TX, id,
75 QE_CR_PROTOCOL_UNSPECIFIED, 0);
76}
77
78void ucc_slow_stop_tx(struct ucc_slow_private * uccs)
79{
80 struct ucc_slow_info *us_info = uccs->us_info;
81 u32 id;
82
83 id = ucc_slow_get_qe_cr_subblock(us_info->ucc_num);
84 qe_issue_cmd(QE_STOP_TX, id, QE_CR_PROTOCOL_UNSPECIFIED, 0);
85}
86
87void ucc_slow_restart_tx(struct ucc_slow_private * uccs)
88{
89 struct ucc_slow_info *us_info = uccs->us_info;
90 u32 id;
91
92 id = ucc_slow_get_qe_cr_subblock(us_info->ucc_num);
93 qe_issue_cmd(QE_RESTART_TX, id, QE_CR_PROTOCOL_UNSPECIFIED, 0);
94}
95
96void ucc_slow_enable(struct ucc_slow_private * uccs, enum comm_dir mode)
97{
98 struct ucc_slow *us_regs;
99 u32 gumr_l;
100
101 us_regs = uccs->us_regs;
102
103 /* Enable reception and/or transmission on this UCC. */
104 gumr_l = in_be32(&us_regs->gumr_l);
105 if (mode & COMM_DIR_TX) {
106 gumr_l |= UCC_SLOW_GUMR_L_ENT;
107 uccs->enabled_tx = 1;
108 }
109 if (mode & COMM_DIR_RX) {
110 gumr_l |= UCC_SLOW_GUMR_L_ENR;
111 uccs->enabled_rx = 1;
112 }
113 out_be32(&us_regs->gumr_l, gumr_l);
114}
115
116void ucc_slow_disable(struct ucc_slow_private * uccs, enum comm_dir mode)
117{
118 struct ucc_slow *us_regs;
119 u32 gumr_l;
120
121 us_regs = uccs->us_regs;
122
123 /* Disable reception and/or transmission on this UCC. */
124 gumr_l = in_be32(&us_regs->gumr_l);
125 if (mode & COMM_DIR_TX) {
126 gumr_l &= ~UCC_SLOW_GUMR_L_ENT;
127 uccs->enabled_tx = 0;
128 }
129 if (mode & COMM_DIR_RX) {
130 gumr_l &= ~UCC_SLOW_GUMR_L_ENR;
131 uccs->enabled_rx = 0;
132 }
133 out_be32(&us_regs->gumr_l, gumr_l);
134}
135
136int ucc_slow_init(struct ucc_slow_info * us_info, struct ucc_slow_private ** uccs_ret)
137{
138 u32 i;
139 struct ucc_slow *us_regs;
140 u32 gumr;
141 u8 function_code = 0;
142 u8 *bd;
143 struct ucc_slow_private *uccs;
144 u32 id;
145 u32 command;
146 int ret;
147
148 uccs_vdbg("%s: IN", __FUNCTION__);
149
150 if (!us_info)
151 return -EINVAL;
152
153 /* check if the UCC port number is in range. */
154 if ((us_info->ucc_num < 0) || (us_info->ucc_num > UCC_MAX_NUM - 1)) {
155 uccs_err("ucc_slow_init: Illagal UCC number!");
156 return -EINVAL;
157 }
158
159 /*
160 * Set mrblr
161 * Check that 'max_rx_buf_length' is properly aligned (4), unless
162 * rfw is 1, meaning that QE accepts one byte at a time, unlike normal
163 * case when QE accepts 32 bits at a time.
164 */
165 if ((!us_info->rfw) &&
166 (us_info->max_rx_buf_length & (UCC_SLOW_MRBLR_ALIGNMENT - 1))) {
167 uccs_err("max_rx_buf_length not aligned.");
168 return -EINVAL;
169 }
170
171 uccs = (struct ucc_slow_private *)
172 kmalloc(sizeof(struct ucc_slow_private), GFP_KERNEL);
173 if (!uccs) {
174 uccs_err
175 ("ucc_slow_init: No memory for UCC slow data structure!");
176 return -ENOMEM;
177 }
178 memset(uccs, 0, sizeof(struct ucc_slow_private));
179
180 /* Fill slow UCC structure */
181 uccs->us_info = us_info;
182 uccs->saved_uccm = 0;
183 uccs->p_rx_frame = 0;
184 uccs->us_regs = us_info->us_regs;
185 us_regs = uccs->us_regs;
186 uccs->p_ucce = (u16 *) & (us_regs->ucce);
187 uccs->p_uccm = (u16 *) & (us_regs->uccm);
188#ifdef STATISTICS
189 uccs->rx_frames = 0;
190 uccs->tx_frames = 0;
191 uccs->rx_discarded = 0;
192#endif /* STATISTICS */
193
194 /* Get PRAM base */
195 uccs->us_pram_offset = qe_muram_alloc(UCC_SLOW_PRAM_SIZE,
196 ALIGNMENT_OF_UCC_SLOW_PRAM);
197 if (IS_MURAM_ERR(uccs->us_pram_offset)) {
198 uccs_err
199 ("ucc_slow_init: Can not allocate MURAM memory "
200 "for Slow UCC.");
201 ucc_slow_free(uccs);
202 return -ENOMEM;
203 }
204 id = ucc_slow_get_qe_cr_subblock(us_info->ucc_num);
205 qe_issue_cmd(QE_ASSIGN_PAGE_TO_DEVICE, id, QE_CR_PROTOCOL_UNSPECIFIED,
206 (u32) uccs->us_pram_offset);
207
208 uccs->us_pram = qe_muram_addr(uccs->us_pram_offset);
209
210 /* Init Guemr register */
211 if ((ret = ucc_init_guemr((struct ucc_common *) (us_info->us_regs)))) {
212 uccs_err("ucc_slow_init: Could not init the guemr register.");
213 ucc_slow_free(uccs);
214 return ret;
215 }
216
217 /* Set UCC to slow type */
218 if ((ret = ucc_set_type(us_info->ucc_num,
219 (struct ucc_common *) (us_info->us_regs),
220 UCC_SPEED_TYPE_SLOW))) {
221 uccs_err("ucc_slow_init: Could not init the guemr register.");
222 ucc_slow_free(uccs);
223 return ret;
224 }
225
226 out_be16(&uccs->us_pram->mrblr, us_info->max_rx_buf_length);
227
228 INIT_LIST_HEAD(&uccs->confQ);
229
230 /* Allocate BDs. */
231 uccs->rx_base_offset =
232 qe_muram_alloc(us_info->rx_bd_ring_len * sizeof(struct qe_bd),
233 QE_ALIGNMENT_OF_BD);
234 if (IS_MURAM_ERR(uccs->rx_base_offset)) {
235 uccs_err("ucc_slow_init: No memory for Rx BD's.");
236 uccs->rx_base_offset = 0;
237 ucc_slow_free(uccs);
238 return -ENOMEM;
239 }
240
241 uccs->tx_base_offset =
242 qe_muram_alloc(us_info->tx_bd_ring_len * sizeof(struct qe_bd),
243 QE_ALIGNMENT_OF_BD);
244 if (IS_MURAM_ERR(uccs->tx_base_offset)) {
245 uccs_err("ucc_slow_init: No memory for Tx BD's.");
246 uccs->tx_base_offset = 0;
247 ucc_slow_free(uccs);
248 return -ENOMEM;
249 }
250
251 /* Init Tx bds */
252 bd = uccs->confBd = uccs->tx_bd = qe_muram_addr(uccs->tx_base_offset);
253 for (i = 0; i < us_info->tx_bd_ring_len; i++) {
254 /* clear bd buffer */
255 out_be32(&(((struct qe_bd *)bd)->buf), 0);
256 /* set bd status and length */
257 out_be32((u32*)bd, 0);
258 bd += sizeof(struct qe_bd);
259 }
260 bd -= sizeof(struct qe_bd);
261 /* set bd status and length */
262 out_be32((u32*)bd, T_W); /* for last BD set Wrap bit */
263
264 /* Init Rx bds */
265 bd = uccs->rx_bd = qe_muram_addr(uccs->rx_base_offset);
266 for (i = 0; i < us_info->rx_bd_ring_len; i++) {
267 /* set bd status and length */
268 out_be32((u32*)bd, 0);
269 /* clear bd buffer */
270 out_be32(&(((struct qe_bd *)bd)->buf), 0);
271 bd += sizeof(struct qe_bd);
272 }
273 bd -= sizeof(struct qe_bd);
274 /* set bd status and length */
275 out_be32((u32*)bd, R_W); /* for last BD set Wrap bit */
276
277 /* Set GUMR (For more details see the hardware spec.). */
278 /* gumr_h */
279 gumr = 0;
280 gumr |= us_info->tcrc;
281 if (us_info->cdp)
282 gumr |= UCC_SLOW_GUMR_H_CDP;
283 if (us_info->ctsp)
284 gumr |= UCC_SLOW_GUMR_H_CTSP;
285 if (us_info->cds)
286 gumr |= UCC_SLOW_GUMR_H_CDS;
287 if (us_info->ctss)
288 gumr |= UCC_SLOW_GUMR_H_CTSS;
289 if (us_info->tfl)
290 gumr |= UCC_SLOW_GUMR_H_TFL;
291 if (us_info->rfw)
292 gumr |= UCC_SLOW_GUMR_H_RFW;
293 if (us_info->txsy)
294 gumr |= UCC_SLOW_GUMR_H_TXSY;
295 if (us_info->rtsm)
296 gumr |= UCC_SLOW_GUMR_H_RTSM;
297 out_be32(&us_regs->gumr_h, gumr);
298
299 /* gumr_l */
300 gumr = 0;
301 if (us_info->tci)
302 gumr |= UCC_SLOW_GUMR_L_TCI;
303 if (us_info->rinv)
304 gumr |= UCC_SLOW_GUMR_L_RINV;
305 if (us_info->tinv)
306 gumr |= UCC_SLOW_GUMR_L_TINV;
307 if (us_info->tend)
308 gumr |= UCC_SLOW_GUMR_L_TEND;
309 gumr |= us_info->tdcr;
310 gumr |= us_info->rdcr;
311 gumr |= us_info->tenc;
312 gumr |= us_info->renc;
313 gumr |= us_info->diag;
314 gumr |= us_info->mode;
315 out_be32(&us_regs->gumr_l, gumr);
316
317 /* Function code registers */
318 /* function_code has initial value 0 */
319
320 /* if the data is in cachable memory, the 'global' */
321 /* in the function code should be set. */
322 function_code |= us_info->data_mem_part;
323 function_code |= QE_BMR_BYTE_ORDER_BO_MOT; /* Required for QE */
324 uccs->us_pram->tfcr = function_code;
325 uccs->us_pram->rfcr = function_code;
326
327 /* rbase, tbase are offsets from MURAM base */
328 out_be16(&uccs->us_pram->rbase, uccs->us_pram_offset);
329 out_be16(&uccs->us_pram->tbase, uccs->us_pram_offset);
330
331 /* Mux clocking */
332 /* Grant Support */
333 ucc_set_qe_mux_grant(us_info->ucc_num, us_info->grant_support);
334 /* Breakpoint Support */
335 ucc_set_qe_mux_bkpt(us_info->ucc_num, us_info->brkpt_support);
336 /* Set Tsa or NMSI mode. */
337 ucc_set_qe_mux_tsa(us_info->ucc_num, us_info->tsa);
338 /* If NMSI (not Tsa), set Tx and Rx clock. */
339 if (!us_info->tsa) {
340 /* Rx clock routing */
341 if (ucc_set_qe_mux_rxtx
342 (us_info->ucc_num, us_info->rx_clock, COMM_DIR_RX)) {
343 uccs_err
344 ("ucc_slow_init: Illegal value for parameter"
345 " 'RxClock'.");
346 ucc_slow_free(uccs);
347 return -EINVAL;
348 }
349 /* Tx clock routing */
350 if (ucc_set_qe_mux_rxtx(us_info->ucc_num,
351 us_info->tx_clock, COMM_DIR_TX)) {
352 uccs_err
353 ("ucc_slow_init: Illegal value for parameter "
354 "'TxClock'.");
355 ucc_slow_free(uccs);
356 return -EINVAL;
357 }
358 }
359
360 /*
361 * INTERRUPTS
362 */
363 /* Set interrupt mask register at UCC level. */
364 out_be16(&us_regs->uccm, us_info->uccm_mask);
365
366 /* First, clear anything pending at UCC level, */
367 /* otherwise, old garbage may come through */
368 /* as soon as the dam is opened. */
369
370 /* Writing '1' clears */
371 out_be16(&us_regs->ucce, 0xffff);
372
373 /* Issue QE Init command */
374 if (us_info->init_tx && us_info->init_rx)
375 command = QE_INIT_TX_RX;
376 else if (us_info->init_tx)
377 command = QE_INIT_TX;
378 else
379 command = QE_INIT_RX; /* We know at least one is TRUE */
380 id = ucc_slow_get_qe_cr_subblock(us_info->ucc_num);
381 qe_issue_cmd(command, id, QE_CR_PROTOCOL_UNSPECIFIED, 0);
382
383 *uccs_ret = uccs;
384 return 0;
385}
386
387void ucc_slow_free(struct ucc_slow_private * uccs)
388{
389 if (!uccs)
390 return;
391
392 if (uccs->rx_base_offset)
393 qe_muram_free(uccs->rx_base_offset);
394
395 if (uccs->tx_base_offset)
396 qe_muram_free(uccs->tx_base_offset);
397
398 if (uccs->us_pram) {
399 qe_muram_free(uccs->us_pram_offset);
400 uccs->us_pram = NULL;
401 }
402
403 kfree(uccs);
404}