aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/sysdev/qe_lib/qe_io.c
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/qe_lib/qe_io.c
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/qe_lib/qe_io.c')
-rw-r--r--arch/powerpc/sysdev/qe_lib/qe_io.c226
1 files changed, 226 insertions, 0 deletions
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 */