~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/arch/powerpc/platforms/44x/gpio.c

Version: ~ [ linux-6.11-rc3 ] ~ [ linux-6.10.4 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.45 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.104 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.164 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.223 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.281 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.319 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 // SPDX-License-Identifier: GPL-2.0-only
  2 /*
  3  * PPC4xx gpio driver
  4  *
  5  * Copyright (c) 2008 Harris Corporation
  6  * Copyright (c) 2008 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
  7  * Copyright (c) MontaVista Software, Inc. 2008.
  8  *
  9  * Author: Steve Falco <sfalco@harris.com>
 10  */
 11 
 12 #include <linux/kernel.h>
 13 #include <linux/init.h>
 14 #include <linux/spinlock.h>
 15 #include <linux/io.h>
 16 #include <linux/of.h>
 17 #include <linux/gpio/legacy-of-mm-gpiochip.h>
 18 #include <linux/gpio/driver.h>
 19 #include <linux/types.h>
 20 #include <linux/slab.h>
 21 
 22 #define GPIO_MASK(gpio)         (0x80000000 >> (gpio))
 23 #define GPIO_MASK2(gpio)        (0xc0000000 >> ((gpio) * 2))
 24 
 25 /* Physical GPIO register layout */
 26 struct ppc4xx_gpio {
 27         __be32 or;
 28         __be32 tcr;
 29         __be32 osrl;
 30         __be32 osrh;
 31         __be32 tsrl;
 32         __be32 tsrh;
 33         __be32 odr;
 34         __be32 ir;
 35         __be32 rr1;
 36         __be32 rr2;
 37         __be32 rr3;
 38         __be32 reserved1;
 39         __be32 isr1l;
 40         __be32 isr1h;
 41         __be32 isr2l;
 42         __be32 isr2h;
 43         __be32 isr3l;
 44         __be32 isr3h;
 45 };
 46 
 47 struct ppc4xx_gpio_chip {
 48         struct of_mm_gpio_chip mm_gc;
 49         spinlock_t lock;
 50 };
 51 
 52 /*
 53  * GPIO LIB API implementation for GPIOs
 54  *
 55  * There are a maximum of 32 gpios in each gpio controller.
 56  */
 57 
 58 static int ppc4xx_gpio_get(struct gpio_chip *gc, unsigned int gpio)
 59 {
 60         struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
 61         struct ppc4xx_gpio __iomem *regs = mm_gc->regs;
 62 
 63         return !!(in_be32(&regs->ir) & GPIO_MASK(gpio));
 64 }
 65 
 66 static inline void
 67 __ppc4xx_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val)
 68 {
 69         struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
 70         struct ppc4xx_gpio __iomem *regs = mm_gc->regs;
 71 
 72         if (val)
 73                 setbits32(&regs->or, GPIO_MASK(gpio));
 74         else
 75                 clrbits32(&regs->or, GPIO_MASK(gpio));
 76 }
 77 
 78 static void
 79 ppc4xx_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val)
 80 {
 81         struct ppc4xx_gpio_chip *chip = gpiochip_get_data(gc);
 82         unsigned long flags;
 83 
 84         spin_lock_irqsave(&chip->lock, flags);
 85 
 86         __ppc4xx_gpio_set(gc, gpio, val);
 87 
 88         spin_unlock_irqrestore(&chip->lock, flags);
 89 
 90         pr_debug("%s: gpio: %d val: %d\n", __func__, gpio, val);
 91 }
 92 
 93 static int ppc4xx_gpio_dir_in(struct gpio_chip *gc, unsigned int gpio)
 94 {
 95         struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
 96         struct ppc4xx_gpio_chip *chip = gpiochip_get_data(gc);
 97         struct ppc4xx_gpio __iomem *regs = mm_gc->regs;
 98         unsigned long flags;
 99 
100         spin_lock_irqsave(&chip->lock, flags);
101 
102         /* Disable open-drain function */
103         clrbits32(&regs->odr, GPIO_MASK(gpio));
104 
105         /* Float the pin */
106         clrbits32(&regs->tcr, GPIO_MASK(gpio));
107 
108         /* Bits 0-15 use TSRL/OSRL, bits 16-31 use TSRH/OSRH */
109         if (gpio < 16) {
110                 clrbits32(&regs->osrl, GPIO_MASK2(gpio));
111                 clrbits32(&regs->tsrl, GPIO_MASK2(gpio));
112         } else {
113                 clrbits32(&regs->osrh, GPIO_MASK2(gpio));
114                 clrbits32(&regs->tsrh, GPIO_MASK2(gpio));
115         }
116 
117         spin_unlock_irqrestore(&chip->lock, flags);
118 
119         return 0;
120 }
121 
122 static int
123 ppc4xx_gpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val)
124 {
125         struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
126         struct ppc4xx_gpio_chip *chip = gpiochip_get_data(gc);
127         struct ppc4xx_gpio __iomem *regs = mm_gc->regs;
128         unsigned long flags;
129 
130         spin_lock_irqsave(&chip->lock, flags);
131 
132         /* First set initial value */
133         __ppc4xx_gpio_set(gc, gpio, val);
134 
135         /* Disable open-drain function */
136         clrbits32(&regs->odr, GPIO_MASK(gpio));
137 
138         /* Drive the pin */
139         setbits32(&regs->tcr, GPIO_MASK(gpio));
140 
141         /* Bits 0-15 use TSRL, bits 16-31 use TSRH */
142         if (gpio < 16) {
143                 clrbits32(&regs->osrl, GPIO_MASK2(gpio));
144                 clrbits32(&regs->tsrl, GPIO_MASK2(gpio));
145         } else {
146                 clrbits32(&regs->osrh, GPIO_MASK2(gpio));
147                 clrbits32(&regs->tsrh, GPIO_MASK2(gpio));
148         }
149 
150         spin_unlock_irqrestore(&chip->lock, flags);
151 
152         pr_debug("%s: gpio: %d val: %d\n", __func__, gpio, val);
153 
154         return 0;
155 }
156 
157 static int __init ppc4xx_add_gpiochips(void)
158 {
159         struct device_node *np;
160 
161         for_each_compatible_node(np, NULL, "ibm,ppc4xx-gpio") {
162                 int ret;
163                 struct ppc4xx_gpio_chip *ppc4xx_gc;
164                 struct of_mm_gpio_chip *mm_gc;
165                 struct gpio_chip *gc;
166 
167                 ppc4xx_gc = kzalloc(sizeof(*ppc4xx_gc), GFP_KERNEL);
168                 if (!ppc4xx_gc) {
169                         ret = -ENOMEM;
170                         goto err;
171                 }
172 
173                 spin_lock_init(&ppc4xx_gc->lock);
174 
175                 mm_gc = &ppc4xx_gc->mm_gc;
176                 gc = &mm_gc->gc;
177 
178                 gc->ngpio = 32;
179                 gc->direction_input = ppc4xx_gpio_dir_in;
180                 gc->direction_output = ppc4xx_gpio_dir_out;
181                 gc->get = ppc4xx_gpio_get;
182                 gc->set = ppc4xx_gpio_set;
183 
184                 ret = of_mm_gpiochip_add_data(np, mm_gc, ppc4xx_gc);
185                 if (ret)
186                         goto err;
187                 continue;
188 err:
189                 pr_err("%pOF: registration failed with status %d\n", np, ret);
190                 kfree(ppc4xx_gc);
191                 /* try others anyway */
192         }
193         return 0;
194 }
195 arch_initcall(ppc4xx_add_gpiochips);
196 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php