diff options
Diffstat (limited to 'arch/powerpc/sysdev/cpm2_common.c')
-rw-r--r-- | arch/powerpc/sysdev/cpm2_common.c | 178 |
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 | ||
47 | static void cpm2_dpinit(void); | 50 | static void cpm2_dpinit(void); |
48 | cpm_cpm2_t *cpmp; /* Pointer to comm processor space */ | 51 | #endif |
52 | |||
53 | cpm_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 | */ |
53 | cpm2_map_t *cpm2_immr; | 58 | cpm2_map_t __iomem *cpm2_immr; |
54 | intctl_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; | |||
60 | void | 64 | void |
61 | cpm2_reset(void) | 65 | cpm2_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) | |||
91 | void | 102 | void |
92 | cpm_setbrg(uint brg, uint rate) | 103 | cpm_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) | |||
113 | void | 124 | void |
114 | cpm2_fastbrg(uint brg, uint rate, int div16) | 125 | cpm2_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 | ||
270 | int 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... */ |
229 | static rh_block_t cpm_boot_dpmem_rh_block[16]; | 333 | static rh_block_t cpm_boot_dpmem_rh_block[16]; |
230 | static rh_info_t cpm_dpmem_info; | 334 | static rh_info_t cpm_dpmem_info; |
231 | static u8* im_dprambase; | 335 | static u8 __iomem *im_dprambase; |
232 | 336 | ||
233 | static void cpm2_dpinit(void) | 337 | static 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 | } |
308 | EXPORT_SYMBOL(cpm_dpram_addr); | 412 | EXPORT_SYMBOL(cpm_dpram_addr); |
413 | #endif /* !CONFIG_PPC_CPM_NEW_BINDING */ | ||
414 | |||
415 | struct cpm2_ioports { | ||
416 | u32 dir, par, sor, odr, dat; | ||
417 | u32 res[3]; | ||
418 | }; | ||
419 | |||
420 | void 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 | } | ||