aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/sysdev/cpm2_common.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/sysdev/cpm2_common.c')
-rw-r--r--arch/powerpc/sysdev/cpm2_common.c178
1 files changed, 158 insertions, 20 deletions
diff --git a/arch/powerpc/sysdev/cpm2_common.c b/arch/powerpc/sysdev/cpm2_common.c
index c827715a5090..859362fecb7c 100644
--- a/arch/powerpc/sysdev/cpm2_common.c
+++ b/arch/powerpc/sysdev/cpm2_common.c
@@ -33,6 +33,8 @@
33#include <linux/mm.h> 33#include <linux/mm.h>
34#include <linux/interrupt.h> 34#include <linux/interrupt.h>
35#include <linux/module.h> 35#include <linux/module.h>
36#include <linux/of.h>
37
36#include <asm/io.h> 38#include <asm/io.h>
37#include <asm/irq.h> 39#include <asm/irq.h>
38#include <asm/mpc8260.h> 40#include <asm/mpc8260.h>
@@ -44,14 +46,16 @@
44 46
45#include <sysdev/fsl_soc.h> 47#include <sysdev/fsl_soc.h>
46 48
49#ifndef CONFIG_PPC_CPM_NEW_BINDING
47static void cpm2_dpinit(void); 50static void cpm2_dpinit(void);
48cpm_cpm2_t *cpmp; /* Pointer to comm processor space */ 51#endif
52
53cpm_cpm2_t __iomem *cpmp; /* Pointer to comm processor space */
49 54
50/* We allocate this here because it is used almost exclusively for 55/* We allocate this here because it is used almost exclusively for
51 * the communication processor devices. 56 * the communication processor devices.
52 */ 57 */
53cpm2_map_t *cpm2_immr; 58cpm2_map_t __iomem *cpm2_immr;
54intctl_cpm2_t *cpm2_intctl;
55 59
56#define CPM_MAP_SIZE (0x40000) /* 256k - the PQ3 reserve this amount 60#define CPM_MAP_SIZE (0x40000) /* 256k - the PQ3 reserve this amount
57 of space for CPM as it is larger 61 of space for CPM as it is larger
@@ -60,12 +64,19 @@ intctl_cpm2_t *cpm2_intctl;
60void 64void
61cpm2_reset(void) 65cpm2_reset(void)
62{ 66{
63 cpm2_immr = (cpm2_map_t *)ioremap(CPM_MAP_ADDR, CPM_MAP_SIZE); 67#ifdef CONFIG_PPC_85xx
64 cpm2_intctl = cpm2_map(im_intctl); 68 cpm2_immr = ioremap(CPM_MAP_ADDR, CPM_MAP_SIZE);
69#else
70 cpm2_immr = ioremap(get_immrbase(), CPM_MAP_SIZE);
71#endif
65 72
66 /* Reclaim the DP memory for our use. 73 /* Reclaim the DP memory for our use.
67 */ 74 */
75#ifdef CONFIG_PPC_CPM_NEW_BINDING
76 cpm_muram_init();
77#else
68 cpm2_dpinit(); 78 cpm2_dpinit();
79#endif
69 80
70 /* Tell everyone where the comm processor resides. 81 /* Tell everyone where the comm processor resides.
71 */ 82 */
@@ -91,7 +102,7 @@ cpm2_reset(void)
91void 102void
92cpm_setbrg(uint brg, uint rate) 103cpm_setbrg(uint brg, uint rate)
93{ 104{
94 volatile uint *bp; 105 u32 __iomem *bp;
95 106
96 /* This is good enough to get SMCs running..... 107 /* This is good enough to get SMCs running.....
97 */ 108 */
@@ -113,7 +124,8 @@ cpm_setbrg(uint brg, uint rate)
113void 124void
114cpm2_fastbrg(uint brg, uint rate, int div16) 125cpm2_fastbrg(uint brg, uint rate, int div16)
115{ 126{
116 volatile uint *bp; 127 u32 __iomem *bp;
128 u32 val;
117 129
118 if (brg < 4) { 130 if (brg < 4) {
119 bp = cpm2_map_size(im_brgc1, 16); 131 bp = cpm2_map_size(im_brgc1, 16);
@@ -123,10 +135,11 @@ cpm2_fastbrg(uint brg, uint rate, int div16)
123 brg -= 4; 135 brg -= 4;
124 } 136 }
125 bp += brg; 137 bp += brg;
126 *bp = ((BRG_INT_CLK / rate) << 1) | CPM_BRG_EN; 138 val = ((BRG_INT_CLK / rate) << 1) | CPM_BRG_EN;
127 if (div16) 139 if (div16)
128 *bp |= CPM_BRG_DIV16; 140 val |= CPM_BRG_DIV16;
129 141
142 out_be32(bp, val);
130 cpm2_unmap(bp); 143 cpm2_unmap(bp);
131} 144}
132 145
@@ -135,10 +148,11 @@ int cpm2_clk_setup(enum cpm_clk_target target, int clock, int mode)
135 int ret = 0; 148 int ret = 0;
136 int shift; 149 int shift;
137 int i, bits = 0; 150 int i, bits = 0;
138 cpmux_t *im_cpmux; 151 cpmux_t __iomem *im_cpmux;
139 u32 *reg; 152 u32 __iomem *reg;
140 u32 mask = 7; 153 u32 mask = 7;
141 u8 clk_map [24][3] = { 154
155 u8 clk_map[][3] = {
142 {CPM_CLK_FCC1, CPM_BRG5, 0}, 156 {CPM_CLK_FCC1, CPM_BRG5, 0},
143 {CPM_CLK_FCC1, CPM_BRG6, 1}, 157 {CPM_CLK_FCC1, CPM_BRG6, 1},
144 {CPM_CLK_FCC1, CPM_BRG7, 2}, 158 {CPM_CLK_FCC1, CPM_BRG7, 2},
@@ -162,8 +176,40 @@ int cpm2_clk_setup(enum cpm_clk_target target, int clock, int mode)
162 {CPM_CLK_FCC3, CPM_CLK13, 4}, 176 {CPM_CLK_FCC3, CPM_CLK13, 4},
163 {CPM_CLK_FCC3, CPM_CLK14, 5}, 177 {CPM_CLK_FCC3, CPM_CLK14, 5},
164 {CPM_CLK_FCC3, CPM_CLK15, 6}, 178 {CPM_CLK_FCC3, CPM_CLK15, 6},
165 {CPM_CLK_FCC3, CPM_CLK16, 7} 179 {CPM_CLK_FCC3, CPM_CLK16, 7},
166 }; 180 {CPM_CLK_SCC1, CPM_BRG1, 0},
181 {CPM_CLK_SCC1, CPM_BRG2, 1},
182 {CPM_CLK_SCC1, CPM_BRG3, 2},
183 {CPM_CLK_SCC1, CPM_BRG4, 3},
184 {CPM_CLK_SCC1, CPM_CLK11, 4},
185 {CPM_CLK_SCC1, CPM_CLK12, 5},
186 {CPM_CLK_SCC1, CPM_CLK3, 6},
187 {CPM_CLK_SCC1, CPM_CLK4, 7},
188 {CPM_CLK_SCC2, CPM_BRG1, 0},
189 {CPM_CLK_SCC2, CPM_BRG2, 1},
190 {CPM_CLK_SCC2, CPM_BRG3, 2},
191 {CPM_CLK_SCC2, CPM_BRG4, 3},
192 {CPM_CLK_SCC2, CPM_CLK11, 4},
193 {CPM_CLK_SCC2, CPM_CLK12, 5},
194 {CPM_CLK_SCC2, CPM_CLK3, 6},
195 {CPM_CLK_SCC2, CPM_CLK4, 7},
196 {CPM_CLK_SCC3, CPM_BRG1, 0},
197 {CPM_CLK_SCC3, CPM_BRG2, 1},
198 {CPM_CLK_SCC3, CPM_BRG3, 2},
199 {CPM_CLK_SCC3, CPM_BRG4, 3},
200 {CPM_CLK_SCC3, CPM_CLK5, 4},
201 {CPM_CLK_SCC3, CPM_CLK6, 5},
202 {CPM_CLK_SCC3, CPM_CLK7, 6},
203 {CPM_CLK_SCC3, CPM_CLK8, 7},
204 {CPM_CLK_SCC4, CPM_BRG1, 0},
205 {CPM_CLK_SCC4, CPM_BRG2, 1},
206 {CPM_CLK_SCC4, CPM_BRG3, 2},
207 {CPM_CLK_SCC4, CPM_BRG4, 3},
208 {CPM_CLK_SCC4, CPM_CLK5, 4},
209 {CPM_CLK_SCC4, CPM_CLK6, 5},
210 {CPM_CLK_SCC4, CPM_CLK7, 6},
211 {CPM_CLK_SCC4, CPM_CLK8, 7},
212 };
167 213
168 im_cpmux = cpm2_map(im_cpmux); 214 im_cpmux = cpm2_map(im_cpmux);
169 215
@@ -201,25 +247,83 @@ int cpm2_clk_setup(enum cpm_clk_target target, int clock, int mode)
201 } 247 }
202 248
203 if (mode == CPM_CLK_RX) 249 if (mode == CPM_CLK_RX)
204 shift +=3; 250 shift += 3;
205 251
206 for (i=0; i<24; i++) { 252 for (i = 0; i < ARRAY_SIZE(clk_map); i++) {
207 if (clk_map[i][0] == target && clk_map[i][1] == clock) { 253 if (clk_map[i][0] == target && clk_map[i][1] == clock) {
208 bits = clk_map[i][2]; 254 bits = clk_map[i][2];
209 break; 255 break;
210 } 256 }
211 } 257 }
212 if (i == sizeof(clk_map)/3) 258 if (i == ARRAY_SIZE(clk_map))
213 ret = -EINVAL; 259 ret = -EINVAL;
214 260
215 bits <<= shift; 261 bits <<= shift;
216 mask <<= shift; 262 mask <<= shift;
263
217 out_be32(reg, (in_be32(reg) & ~mask) | bits); 264 out_be32(reg, (in_be32(reg) & ~mask) | bits);
218 265
219 cpm2_unmap(im_cpmux); 266 cpm2_unmap(im_cpmux);
220 return ret; 267 return ret;
221} 268}
222 269
270int cpm2_smc_clk_setup(enum cpm_clk_target target, int clock)
271{
272 int ret = 0;
273 int shift;
274 int i, bits = 0;
275 cpmux_t __iomem *im_cpmux;
276 u8 __iomem *reg;
277 u8 mask = 3;
278
279 u8 clk_map[][3] = {
280 {CPM_CLK_SMC1, CPM_BRG1, 0},
281 {CPM_CLK_SMC1, CPM_BRG7, 1},
282 {CPM_CLK_SMC1, CPM_CLK7, 2},
283 {CPM_CLK_SMC1, CPM_CLK9, 3},
284 {CPM_CLK_SMC2, CPM_BRG2, 0},
285 {CPM_CLK_SMC2, CPM_BRG8, 1},
286 {CPM_CLK_SMC2, CPM_CLK4, 2},
287 {CPM_CLK_SMC2, CPM_CLK15, 3},
288 };
289
290 im_cpmux = cpm2_map(im_cpmux);
291
292 switch (target) {
293 case CPM_CLK_SMC1:
294 reg = &im_cpmux->cmx_smr;
295 mask = 3;
296 shift = 4;
297 break;
298 case CPM_CLK_SMC2:
299 reg = &im_cpmux->cmx_smr;
300 mask = 3;
301 shift = 0;
302 break;
303 default:
304 printk(KERN_ERR "cpm2_smc_clock_setup: invalid clock target\n");
305 return -EINVAL;
306 }
307
308 for (i = 0; i < ARRAY_SIZE(clk_map); i++) {
309 if (clk_map[i][0] == target && clk_map[i][1] == clock) {
310 bits = clk_map[i][2];
311 break;
312 }
313 }
314 if (i == ARRAY_SIZE(clk_map))
315 ret = -EINVAL;
316
317 bits <<= shift;
318 mask <<= shift;
319
320 out_8(reg, (in_8(reg) & ~mask) | bits);
321
322 cpm2_unmap(im_cpmux);
323 return ret;
324}
325
326#ifndef CONFIG_PPC_CPM_NEW_BINDING
223/* 327/*
224 * dpalloc / dpfree bits. 328 * dpalloc / dpfree bits.
225 */ 329 */
@@ -228,20 +332,20 @@ static spinlock_t cpm_dpmem_lock;
228 * until the memory subsystem goes up... */ 332 * until the memory subsystem goes up... */
229static rh_block_t cpm_boot_dpmem_rh_block[16]; 333static rh_block_t cpm_boot_dpmem_rh_block[16];
230static rh_info_t cpm_dpmem_info; 334static rh_info_t cpm_dpmem_info;
231static u8* im_dprambase; 335static u8 __iomem *im_dprambase;
232 336
233static void cpm2_dpinit(void) 337static void cpm2_dpinit(void)
234{ 338{
235 spin_lock_init(&cpm_dpmem_lock); 339 spin_lock_init(&cpm_dpmem_lock);
236 340
237 im_dprambase = ioremap(CPM_MAP_ADDR, CPM_DATAONLY_BASE + CPM_DATAONLY_SIZE);
238
239 /* initialize the info header */ 341 /* initialize the info header */
240 rh_init(&cpm_dpmem_info, 1, 342 rh_init(&cpm_dpmem_info, 1,
241 sizeof(cpm_boot_dpmem_rh_block) / 343 sizeof(cpm_boot_dpmem_rh_block) /
242 sizeof(cpm_boot_dpmem_rh_block[0]), 344 sizeof(cpm_boot_dpmem_rh_block[0]),
243 cpm_boot_dpmem_rh_block); 345 cpm_boot_dpmem_rh_block);
244 346
347 im_dprambase = cpm2_immr;
348
245 /* Attach the usable dpmem area */ 349 /* Attach the usable dpmem area */
246 /* XXX: This is actually crap. CPM_DATAONLY_BASE and 350 /* XXX: This is actually crap. CPM_DATAONLY_BASE and
247 * CPM_DATAONLY_SIZE is only a subset of the available dpram. It 351 * CPM_DATAONLY_SIZE is only a subset of the available dpram. It
@@ -306,3 +410,37 @@ void *cpm_dpram_addr(unsigned long offset)
306 return (void *)(im_dprambase + offset); 410 return (void *)(im_dprambase + offset);
307} 411}
308EXPORT_SYMBOL(cpm_dpram_addr); 412EXPORT_SYMBOL(cpm_dpram_addr);
413#endif /* !CONFIG_PPC_CPM_NEW_BINDING */
414
415struct cpm2_ioports {
416 u32 dir, par, sor, odr, dat;
417 u32 res[3];
418};
419
420void cpm2_set_pin(int port, int pin, int flags)
421{
422 struct cpm2_ioports __iomem *iop =
423 (struct cpm2_ioports __iomem *)&cpm2_immr->im_ioport;
424
425 pin = 1 << (31 - pin);
426
427 if (flags & CPM_PIN_OUTPUT)
428 setbits32(&iop[port].dir, pin);
429 else
430 clrbits32(&iop[port].dir, pin);
431
432 if (!(flags & CPM_PIN_GPIO))
433 setbits32(&iop[port].par, pin);
434 else
435 clrbits32(&iop[port].par, pin);
436
437 if (flags & CPM_PIN_SECONDARY)
438 setbits32(&iop[port].sor, pin);
439 else
440 clrbits32(&iop[port].sor, pin);
441
442 if (flags & CPM_PIN_OPENDRAIN)
443 setbits32(&iop[port].odr, pin);
444 else
445 clrbits32(&iop[port].odr, pin);
446}