aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorJochen Friedrich <jochen@scram.de>2008-07-02 12:18:23 -0400
committerKumar Gala <galak@kernel.crashing.org>2008-07-28 08:42:09 -0400
commitdc2380ec8572fcd7f7e9579afc9fb223300d922f (patch)
treeef83f9d7406aca65c87e84c38fadc6e6f0394f53 /arch
parente193325e3e3de188ae2aa5207adc7129aacc5c9d (diff)
powerpc: implement GPIO LIB API on CPM1 Freescale SoC.
This patch implement GPIO LIB support for the CPM1 GPIOs. Signed-off-by: Jochen Friedrich <jochen@scram.de> Signed-off-by: Kumar Gala <galak@kernel.crashing.org>
Diffstat (limited to 'arch')
-rw-r--r--arch/powerpc/platforms/8xx/Kconfig10
-rw-r--r--arch/powerpc/sysdev/cpm1.c267
2 files changed, 272 insertions, 5 deletions
diff --git a/arch/powerpc/platforms/8xx/Kconfig b/arch/powerpc/platforms/8xx/Kconfig
index 6fc849e51e48..71d7562e190b 100644
--- a/arch/powerpc/platforms/8xx/Kconfig
+++ b/arch/powerpc/platforms/8xx/Kconfig
@@ -105,6 +105,16 @@ config 8xx_COPYBACK
105 105
106 If in doubt, say Y here. 106 If in doubt, say Y here.
107 107
108config 8xx_GPIO
109 bool "GPIO API Support"
110 select GENERIC_GPIO
111 select ARCH_REQUIRE_GPIOLIB
112 help
113 Saying Y here will cause the ports on an MPC8xx processor to be used
114 with the GPIO API. If you say N here, the kernel needs less memory.
115
116 If in doubt, say Y here.
117
108config 8xx_CPU6 118config 8xx_CPU6
109 bool "CPU6 Silicon Errata (860 Pre Rev. C)" 119 bool "CPU6 Silicon Errata (860 Pre Rev. C)"
110 help 120 help
diff --git a/arch/powerpc/sysdev/cpm1.c b/arch/powerpc/sysdev/cpm1.c
index 661df42830b9..4a04823e8423 100644
--- a/arch/powerpc/sysdev/cpm1.c
+++ b/arch/powerpc/sysdev/cpm1.c
@@ -30,6 +30,7 @@
30#include <linux/interrupt.h> 30#include <linux/interrupt.h>
31#include <linux/irq.h> 31#include <linux/irq.h>
32#include <linux/module.h> 32#include <linux/module.h>
33#include <linux/spinlock.h>
33#include <asm/page.h> 34#include <asm/page.h>
34#include <asm/pgtable.h> 35#include <asm/pgtable.h>
35#include <asm/8xx_immap.h> 36#include <asm/8xx_immap.h>
@@ -42,6 +43,10 @@
42 43
43#include <asm/fs_pd.h> 44#include <asm/fs_pd.h>
44 45
46#ifdef CONFIG_8xx_GPIO
47#include <linux/of_gpio.h>
48#endif
49
45#define CPM_MAP_SIZE (0x4000) 50#define CPM_MAP_SIZE (0x4000)
46 51
47cpm8xx_t __iomem *cpmp; /* Pointer to comm processor space */ 52cpm8xx_t __iomem *cpmp; /* Pointer to comm processor space */
@@ -290,20 +295,24 @@ struct cpm_ioport16 {
290 __be16 res[3]; 295 __be16 res[3];
291}; 296};
292 297
293struct cpm_ioport32 { 298struct cpm_ioport32b {
294 __be32 dir, par, sor; 299 __be32 dir, par, odr, dat;
300};
301
302struct cpm_ioport32e {
303 __be32 dir, par, sor, odr, dat;
295}; 304};
296 305
297static void cpm1_set_pin32(int port, int pin, int flags) 306static void cpm1_set_pin32(int port, int pin, int flags)
298{ 307{
299 struct cpm_ioport32 __iomem *iop; 308 struct cpm_ioport32e __iomem *iop;
300 pin = 1 << (31 - pin); 309 pin = 1 << (31 - pin);
301 310
302 if (port == CPM_PORTB) 311 if (port == CPM_PORTB)
303 iop = (struct cpm_ioport32 __iomem *) 312 iop = (struct cpm_ioport32e __iomem *)
304 &mpc8xx_immr->im_cpm.cp_pbdir; 313 &mpc8xx_immr->im_cpm.cp_pbdir;
305 else 314 else
306 iop = (struct cpm_ioport32 __iomem *) 315 iop = (struct cpm_ioport32e __iomem *)
307 &mpc8xx_immr->im_cpm.cp_pedir; 316 &mpc8xx_immr->im_cpm.cp_pedir;
308 317
309 if (flags & CPM_PIN_OUTPUT) 318 if (flags & CPM_PIN_OUTPUT)
@@ -498,3 +507,251 @@ int cpm1_clk_setup(enum cpm_clk_target target, int clock, int mode)
498 507
499 return 0; 508 return 0;
500} 509}
510
511/*
512 * GPIO LIB API implementation
513 */
514#ifdef CONFIG_8xx_GPIO
515
516struct cpm1_gpio16_chip {
517 struct of_mm_gpio_chip mm_gc;
518 spinlock_t lock;
519
520 /* shadowed data register to clear/set bits safely */
521 u16 cpdata;
522};
523
524static inline struct cpm1_gpio16_chip *
525to_cpm1_gpio16_chip(struct of_mm_gpio_chip *mm_gc)
526{
527 return container_of(mm_gc, struct cpm1_gpio16_chip, mm_gc);
528}
529
530static void cpm1_gpio16_save_regs(struct of_mm_gpio_chip *mm_gc)
531{
532 struct cpm1_gpio16_chip *cpm1_gc = to_cpm1_gpio16_chip(mm_gc);
533 struct cpm_ioport16 __iomem *iop = mm_gc->regs;
534
535 cpm1_gc->cpdata = in_be16(&iop->dat);
536}
537
538static int cpm1_gpio16_get(struct gpio_chip *gc, unsigned int gpio)
539{
540 struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
541 struct cpm_ioport16 __iomem *iop = mm_gc->regs;
542 u16 pin_mask;
543
544 pin_mask = 1 << (15 - gpio);
545
546 return !!(in_be16(&iop->dat) & pin_mask);
547}
548
549static void cpm1_gpio16_set(struct gpio_chip *gc, unsigned int gpio, int value)
550{
551 struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
552 struct cpm1_gpio16_chip *cpm1_gc = to_cpm1_gpio16_chip(mm_gc);
553 struct cpm_ioport16 __iomem *iop = mm_gc->regs;
554 unsigned long flags;
555 u16 pin_mask = 1 << (15 - gpio);
556
557 spin_lock_irqsave(&cpm1_gc->lock, flags);
558
559 if (value)
560 cpm1_gc->cpdata |= pin_mask;
561 else
562 cpm1_gc->cpdata &= ~pin_mask;
563
564 out_be16(&iop->dat, cpm1_gc->cpdata);
565
566 spin_unlock_irqrestore(&cpm1_gc->lock, flags);
567}
568
569static int cpm1_gpio16_dir_out(struct gpio_chip *gc, unsigned int gpio, int val)
570{
571 struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
572 struct cpm_ioport16 __iomem *iop = mm_gc->regs;
573 u16 pin_mask;
574
575 pin_mask = 1 << (15 - gpio);
576
577 setbits16(&iop->dir, pin_mask);
578
579 cpm1_gpio16_set(gc, gpio, val);
580
581 return 0;
582}
583
584static int cpm1_gpio16_dir_in(struct gpio_chip *gc, unsigned int gpio)
585{
586 struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
587 struct cpm_ioport16 __iomem *iop = mm_gc->regs;
588 u16 pin_mask;
589
590 pin_mask = 1 << (15 - gpio);
591
592 clrbits16(&iop->dir, pin_mask);
593
594 return 0;
595}
596
597int cpm1_gpiochip_add16(struct device_node *np)
598{
599 struct cpm1_gpio16_chip *cpm1_gc;
600 struct of_mm_gpio_chip *mm_gc;
601 struct of_gpio_chip *of_gc;
602 struct gpio_chip *gc;
603
604 cpm1_gc = kzalloc(sizeof(*cpm1_gc), GFP_KERNEL);
605 if (!cpm1_gc)
606 return -ENOMEM;
607
608 spin_lock_init(&cpm1_gc->lock);
609
610 mm_gc = &cpm1_gc->mm_gc;
611 of_gc = &mm_gc->of_gc;
612 gc = &of_gc->gc;
613
614 mm_gc->save_regs = cpm1_gpio16_save_regs;
615 of_gc->gpio_cells = 2;
616 gc->ngpio = 16;
617 gc->direction_input = cpm1_gpio16_dir_in;
618 gc->direction_output = cpm1_gpio16_dir_out;
619 gc->get = cpm1_gpio16_get;
620 gc->set = cpm1_gpio16_set;
621
622 return of_mm_gpiochip_add(np, mm_gc);
623}
624
625struct cpm1_gpio32_chip {
626 struct of_mm_gpio_chip mm_gc;
627 spinlock_t lock;
628
629 /* shadowed data register to clear/set bits safely */
630 u32 cpdata;
631};
632
633static inline struct cpm1_gpio32_chip *
634to_cpm1_gpio32_chip(struct of_mm_gpio_chip *mm_gc)
635{
636 return container_of(mm_gc, struct cpm1_gpio32_chip, mm_gc);
637}
638
639static void cpm1_gpio32_save_regs(struct of_mm_gpio_chip *mm_gc)
640{
641 struct cpm1_gpio32_chip *cpm1_gc = to_cpm1_gpio32_chip(mm_gc);
642 struct cpm_ioport32b __iomem *iop = mm_gc->regs;
643
644 cpm1_gc->cpdata = in_be32(&iop->dat);
645}
646
647static int cpm1_gpio32_get(struct gpio_chip *gc, unsigned int gpio)
648{
649 struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
650 struct cpm_ioport32b __iomem *iop = mm_gc->regs;
651 u32 pin_mask;
652
653 pin_mask = 1 << (31 - gpio);
654
655 return !!(in_be32(&iop->dat) & pin_mask);
656}
657
658static void cpm1_gpio32_set(struct gpio_chip *gc, unsigned int gpio, int value)
659{
660 struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
661 struct cpm1_gpio32_chip *cpm1_gc = to_cpm1_gpio32_chip(mm_gc);
662 struct cpm_ioport32b __iomem *iop = mm_gc->regs;
663 unsigned long flags;
664 u32 pin_mask = 1 << (31 - gpio);
665
666 spin_lock_irqsave(&cpm1_gc->lock, flags);
667
668 if (value)
669 cpm1_gc->cpdata |= pin_mask;
670 else
671 cpm1_gc->cpdata &= ~pin_mask;
672
673 out_be32(&iop->dat, cpm1_gc->cpdata);
674
675 spin_unlock_irqrestore(&cpm1_gc->lock, flags);
676}
677
678static int cpm1_gpio32_dir_out(struct gpio_chip *gc, unsigned int gpio, int val)
679{
680 struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
681 struct cpm_ioport32b __iomem *iop = mm_gc->regs;
682 u32 pin_mask;
683
684 pin_mask = 1 << (31 - gpio);
685
686 setbits32(&iop->dir, pin_mask);
687
688 cpm1_gpio32_set(gc, gpio, val);
689
690 return 0;
691}
692
693static int cpm1_gpio32_dir_in(struct gpio_chip *gc, unsigned int gpio)
694{
695 struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
696 struct cpm_ioport32b __iomem *iop = mm_gc->regs;
697 u32 pin_mask;
698
699 pin_mask = 1 << (31 - gpio);
700
701 clrbits32(&iop->dir, pin_mask);
702
703 return 0;
704}
705
706int cpm1_gpiochip_add32(struct device_node *np)
707{
708 struct cpm1_gpio32_chip *cpm1_gc;
709 struct of_mm_gpio_chip *mm_gc;
710 struct of_gpio_chip *of_gc;
711 struct gpio_chip *gc;
712
713 cpm1_gc = kzalloc(sizeof(*cpm1_gc), GFP_KERNEL);
714 if (!cpm1_gc)
715 return -ENOMEM;
716
717 spin_lock_init(&cpm1_gc->lock);
718
719 mm_gc = &cpm1_gc->mm_gc;
720 of_gc = &mm_gc->of_gc;
721 gc = &of_gc->gc;
722
723 mm_gc->save_regs = cpm1_gpio32_save_regs;
724 of_gc->gpio_cells = 2;
725 gc->ngpio = 32;
726 gc->direction_input = cpm1_gpio32_dir_in;
727 gc->direction_output = cpm1_gpio32_dir_out;
728 gc->get = cpm1_gpio32_get;
729 gc->set = cpm1_gpio32_set;
730
731 return of_mm_gpiochip_add(np, mm_gc);
732}
733
734static int cpm_init_par_io(void)
735{
736 struct device_node *np;
737
738 for_each_compatible_node(np, NULL, "fsl,cpm1-pario-bank-a")
739 cpm1_gpiochip_add16(np);
740
741 for_each_compatible_node(np, NULL, "fsl,cpm1-pario-bank-b")
742 cpm1_gpiochip_add32(np);
743
744 for_each_compatible_node(np, NULL, "fsl,cpm1-pario-bank-c")
745 cpm1_gpiochip_add16(np);
746
747 for_each_compatible_node(np, NULL, "fsl,cpm1-pario-bank-d")
748 cpm1_gpiochip_add16(np);
749
750 /* Port E uses CPM2 layout */
751 for_each_compatible_node(np, NULL, "fsl,cpm1-pario-bank-e")
752 cpm2_gpiochip_add32(np);
753 return 0;
754}
755arch_initcall(cpm_init_par_io);
756
757#endif /* CONFIG_8xx_GPIO */