aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLaurent Pinchart <laurentp@cse-semaphore.com>2008-07-28 04:43:22 -0400
committerKumar Gala <galak@kernel.crashing.org>2008-07-28 08:40:48 -0400
commite193325e3e3de188ae2aa5207adc7129aacc5c9d (patch)
treeda00df7d2a0e3d40160adbd63cb6408cc3e51f15
parent4c920de37d29284d4cb65d76a97a567247c2ac32 (diff)
cpm2: Implement GPIO LIB API on CPM2 Freescale SoC.
This patch implement GPIO LIB support for the CPM2 GPIOs. The code can also be used for CPM1 GPIO port E, as both cores are compatible at the register level. Based on earlier work by Laurent Pinchart. Signed-off-by: Jochen Friedrich <jochen@scram.de> Cc: Laurent Pinchart <laurentp@cse-semaphore.com> Signed-off-by: Kumar Gala <galak@kernel.crashing.org>
-rw-r--r--arch/powerpc/platforms/Kconfig2
-rw-r--r--arch/powerpc/sysdev/cpm2.c11
-rw-r--r--arch/powerpc/sysdev/cpm_common.c123
-rw-r--r--include/asm-powerpc/cpm.h3
4 files changed, 139 insertions, 0 deletions
diff --git a/arch/powerpc/platforms/Kconfig b/arch/powerpc/platforms/Kconfig
index 1d0968775c0a..18a71839dc9e 100644
--- a/arch/powerpc/platforms/Kconfig
+++ b/arch/powerpc/platforms/Kconfig
@@ -254,6 +254,8 @@ config CPM2
254 select CPM 254 select CPM
255 select PPC_LIB_RHEAP 255 select PPC_LIB_RHEAP
256 select PPC_PCI_CHOICE 256 select PPC_PCI_CHOICE
257 select ARCH_REQUIRE_GPIOLIB
258 select GENERIC_GPIO
257 help 259 help
258 The CPM2 (Communications Processor Module) is a coprocessor on 260 The CPM2 (Communications Processor Module) is a coprocessor on
259 embedded CPUs made by Freescale. Selecting this option means that 261 embedded CPUs made by Freescale. Selecting this option means that
diff --git a/arch/powerpc/sysdev/cpm2.c b/arch/powerpc/sysdev/cpm2.c
index 5a6c5dfc53ef..9311778a5082 100644
--- a/arch/powerpc/sysdev/cpm2.c
+++ b/arch/powerpc/sysdev/cpm2.c
@@ -377,3 +377,14 @@ void cpm2_set_pin(int port, int pin, int flags)
377 else 377 else
378 clrbits32(&iop[port].odr, pin); 378 clrbits32(&iop[port].odr, pin);
379} 379}
380
381static int cpm_init_par_io(void)
382{
383 struct device_node *np;
384
385 for_each_compatible_node(np, NULL, "fsl,cpm2-pario-bank")
386 cpm2_gpiochip_add32(np);
387 return 0;
388}
389arch_initcall(cpm_init_par_io);
390
diff --git a/arch/powerpc/sysdev/cpm_common.c b/arch/powerpc/sysdev/cpm_common.c
index e4b7296acb2c..53da8a079f96 100644
--- a/arch/powerpc/sysdev/cpm_common.c
+++ b/arch/powerpc/sysdev/cpm_common.c
@@ -19,6 +19,8 @@
19 19
20#include <linux/init.h> 20#include <linux/init.h>
21#include <linux/of_device.h> 21#include <linux/of_device.h>
22#include <linux/spinlock.h>
23#include <linux/of.h>
22 24
23#include <asm/udbg.h> 25#include <asm/udbg.h>
24#include <asm/io.h> 26#include <asm/io.h>
@@ -28,6 +30,10 @@
28 30
29#include <mm/mmu_decl.h> 31#include <mm/mmu_decl.h>
30 32
33#if defined(CONFIG_CPM2) || defined(CONFIG_8xx_GPIO)
34#include <linux/of_gpio.h>
35#endif
36
31#ifdef CONFIG_PPC_EARLY_DEBUG_CPM 37#ifdef CONFIG_PPC_EARLY_DEBUG_CPM
32static u32 __iomem *cpm_udbg_txdesc = 38static u32 __iomem *cpm_udbg_txdesc =
33 (u32 __iomem __force *)CONFIG_PPC_EARLY_DEBUG_CPM_ADDR; 39 (u32 __iomem __force *)CONFIG_PPC_EARLY_DEBUG_CPM_ADDR;
@@ -207,3 +213,120 @@ dma_addr_t cpm_muram_dma(void __iomem *addr)
207 return muram_pbase + ((u8 __iomem *)addr - muram_vbase); 213 return muram_pbase + ((u8 __iomem *)addr - muram_vbase);
208} 214}
209EXPORT_SYMBOL(cpm_muram_dma); 215EXPORT_SYMBOL(cpm_muram_dma);
216
217#if defined(CONFIG_CPM2) || defined(CONFIG_8xx_GPIO)
218
219struct cpm2_ioports {
220 u32 dir, par, sor, odr, dat;
221 u32 res[3];
222};
223
224struct cpm2_gpio32_chip {
225 struct of_mm_gpio_chip mm_gc;
226 spinlock_t lock;
227
228 /* shadowed data register to clear/set bits safely */
229 u32 cpdata;
230};
231
232static inline struct cpm2_gpio32_chip *
233to_cpm2_gpio32_chip(struct of_mm_gpio_chip *mm_gc)
234{
235 return container_of(mm_gc, struct cpm2_gpio32_chip, mm_gc);
236}
237
238static void cpm2_gpio32_save_regs(struct of_mm_gpio_chip *mm_gc)
239{
240 struct cpm2_gpio32_chip *cpm2_gc = to_cpm2_gpio32_chip(mm_gc);
241 struct cpm2_ioports __iomem *iop = mm_gc->regs;
242
243 cpm2_gc->cpdata = in_be32(&iop->dat);
244}
245
246static int cpm2_gpio32_get(struct gpio_chip *gc, unsigned int gpio)
247{
248 struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
249 struct cpm2_ioports __iomem *iop = mm_gc->regs;
250 u32 pin_mask;
251
252 pin_mask = 1 << (31 - gpio);
253
254 return !!(in_be32(&iop->dat) & pin_mask);
255}
256
257static void cpm2_gpio32_set(struct gpio_chip *gc, unsigned int gpio, int value)
258{
259 struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
260 struct cpm2_gpio32_chip *cpm2_gc = to_cpm2_gpio32_chip(mm_gc);
261 struct cpm2_ioports __iomem *iop = mm_gc->regs;
262 unsigned long flags;
263 u32 pin_mask = 1 << (31 - gpio);
264
265 spin_lock_irqsave(&cpm2_gc->lock, flags);
266
267 if (value)
268 cpm2_gc->cpdata |= pin_mask;
269 else
270 cpm2_gc->cpdata &= ~pin_mask;
271
272 out_be32(&iop->dat, cpm2_gc->cpdata);
273
274 spin_unlock_irqrestore(&cpm2_gc->lock, flags);
275}
276
277static int cpm2_gpio32_dir_out(struct gpio_chip *gc, unsigned int gpio, int val)
278{
279 struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
280 struct cpm2_ioports __iomem *iop = mm_gc->regs;
281 u32 pin_mask;
282
283 pin_mask = 1 << (31 - gpio);
284
285 setbits32(&iop->dir, pin_mask);
286
287 cpm2_gpio32_set(gc, gpio, val);
288
289 return 0;
290}
291
292static int cpm2_gpio32_dir_in(struct gpio_chip *gc, unsigned int gpio)
293{
294 struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
295 struct cpm2_ioports __iomem *iop = mm_gc->regs;
296 u32 pin_mask;
297
298 pin_mask = 1 << (31 - gpio);
299
300 clrbits32(&iop->dir, pin_mask);
301
302 return 0;
303}
304
305int cpm2_gpiochip_add32(struct device_node *np)
306{
307 struct cpm2_gpio32_chip *cpm2_gc;
308 struct of_mm_gpio_chip *mm_gc;
309 struct of_gpio_chip *of_gc;
310 struct gpio_chip *gc;
311
312 cpm2_gc = kzalloc(sizeof(*cpm2_gc), GFP_KERNEL);
313 if (!cpm2_gc)
314 return -ENOMEM;
315
316 spin_lock_init(&cpm2_gc->lock);
317
318 mm_gc = &cpm2_gc->mm_gc;
319 of_gc = &mm_gc->of_gc;
320 gc = &of_gc->gc;
321
322 mm_gc->save_regs = cpm2_gpio32_save_regs;
323 of_gc->gpio_cells = 2;
324 gc->ngpio = 32;
325 gc->direction_input = cpm2_gpio32_dir_in;
326 gc->direction_output = cpm2_gpio32_dir_out;
327 gc->get = cpm2_gpio32_get;
328 gc->set = cpm2_gpio32_set;
329
330 return of_mm_gpiochip_add(np, mm_gc);
331}
332#endif /* CONFIG_CPM2 || CONFIG_8xx_GPIO */
diff --git a/include/asm-powerpc/cpm.h b/include/asm-powerpc/cpm.h
index 63a55337c2de..24d79e3abd8e 100644
--- a/include/asm-powerpc/cpm.h
+++ b/include/asm-powerpc/cpm.h
@@ -3,6 +3,7 @@
3 3
4#include <linux/compiler.h> 4#include <linux/compiler.h>
5#include <linux/types.h> 5#include <linux/types.h>
6#include <linux/of.h>
6 7
7/* Opcodes common to CPM1 and CPM2 8/* Opcodes common to CPM1 and CPM2
8*/ 9*/
@@ -100,4 +101,6 @@ unsigned long cpm_muram_offset(void __iomem *addr);
100dma_addr_t cpm_muram_dma(void __iomem *addr); 101dma_addr_t cpm_muram_dma(void __iomem *addr);
101int cpm_command(u32 command, u8 opcode); 102int cpm_command(u32 command, u8 opcode);
102 103
104int cpm2_gpiochip_add32(struct device_node *np);
105
103#endif 106#endif