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

TOMOYO Linux Cross Reference
Linux/arch/arm/plat-s3c64xx/gpiolib.c

Version: ~ [ linux-5.15-rc5 ] ~ [ linux-5.14.11 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.72 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.152 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.210 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.250 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.286 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.288 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.18.140 ] ~ [ linux-3.16.85 ] ~ [ linux-3.14.79 ] ~ [ linux-3.12.74 ] ~ [ 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.5 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /* arch/arm/plat-s3c64xx/gpiolib.c
  2  *
  3  * Copyright 2008 Openmoko, Inc.
  4  * Copyright 2008 Simtec Electronics
  5  *      Ben Dooks <ben@simtec.co.uk>
  6  *      http://armlinux.simtec.co.uk/
  7  *
  8  * S3C64XX - GPIOlib support 
  9  *
 10  * This program is free software; you can redistribute it and/or modify
 11  * it under the terms of the GNU General Public License version 2 as
 12  * published by the Free Software Foundation.
 13  */
 14 
 15 #include <linux/kernel.h>
 16 #include <linux/irq.h>
 17 #include <linux/io.h>
 18 
 19 #include <mach/map.h>
 20 #include <mach/gpio.h>
 21 #include <mach/gpio-core.h>
 22 
 23 #include <plat/gpio-cfg.h>
 24 #include <plat/gpio-cfg-helpers.h>
 25 #include <plat/regs-gpio.h>
 26 
 27 /* GPIO bank summary:
 28  *
 29  * Bank GPIOs   Style   SlpCon  ExtInt Group
 30  * A    8       4Bit    Yes     1
 31  * B    7       4Bit    Yes     1
 32  * C    8       4Bit    Yes     2
 33  * D    5       4Bit    Yes     3
 34  * E    5       4Bit    Yes     None
 35  * F    16      2Bit    Yes     4 [1]
 36  * G    7       4Bit    Yes     5
 37  * H    10      4Bit[2] Yes     6
 38  * I    16      2Bit    Yes     None
 39  * J    12      2Bit    Yes     None
 40  * K    16      4Bit[2] No      None
 41  * L    15      4Bit[2] No      None
 42  * M    6       4Bit    No      IRQ_EINT
 43  * N    16      2Bit    No      IRQ_EINT
 44  * O    16      2Bit    Yes     7
 45  * P    15      2Bit    Yes     8
 46  * Q    9       2Bit    Yes     9
 47  *
 48  * [1] BANKF pins 14,15 do not form part of the external interrupt sources
 49  * [2] BANK has two control registers, GPxCON0 and GPxCON1
 50  */
 51 
 52 #define OFF_GPCON       (0x00)
 53 #define OFF_GPDAT       (0x04)
 54 
 55 #define con_4bit_shift(__off) ((__off) * 4)
 56 
 57 #if 1
 58 #define gpio_dbg(x...) do { } while(0)
 59 #else
 60 #define gpio_dbg(x...) printk(KERN_DEBUG x)
 61 #endif
 62 
 63 /* The s3c64xx_gpiolib_4bit routines are to control the gpio banks where
 64  * the gpio configuration register (GPxCON) has 4 bits per GPIO, as the
 65  * following example:
 66  *
 67  * base + 0x00: Control register, 4 bits per gpio
 68  *              gpio n: 4 bits starting at (4*n)
 69  *              0000 = input, 0001 = output, others mean special-function
 70  * base + 0x04: Data register, 1 bit per gpio
 71  *              bit n: data bit n
 72  *
 73  * Note, since the data register is one bit per gpio and is at base + 0x4
 74  * we can use s3c_gpiolib_get and s3c_gpiolib_set to change the state of
 75  * the output.
 76 */
 77 
 78 static int s3c64xx_gpiolib_4bit_input(struct gpio_chip *chip, unsigned offset)
 79 {
 80         struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip);
 81         void __iomem *base = ourchip->base;
 82         unsigned long con;
 83 
 84         con = __raw_readl(base + OFF_GPCON);
 85         con &= ~(0xf << con_4bit_shift(offset));
 86         __raw_writel(con, base + OFF_GPCON);
 87 
 88         gpio_dbg("%s: %p: CON now %08lx\n", __func__, base, con);
 89 
 90         return 0;
 91 }
 92 
 93 static int s3c64xx_gpiolib_4bit_output(struct gpio_chip *chip,
 94                                        unsigned offset, int value)
 95 {
 96         struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip);
 97         void __iomem *base = ourchip->base;
 98         unsigned long con;
 99         unsigned long dat;
100 
101         con = __raw_readl(base + OFF_GPCON);
102         con &= ~(0xf << con_4bit_shift(offset));
103         con |= 0x1 << con_4bit_shift(offset);
104 
105         dat = __raw_readl(base + OFF_GPDAT);
106         if (value)
107                 dat |= 1 << offset;
108         else
109                 dat &= ~(1 << offset);
110 
111         __raw_writel(dat, base + OFF_GPDAT);
112         __raw_writel(con, base + OFF_GPCON);
113         __raw_writel(dat, base + OFF_GPDAT);
114 
115         gpio_dbg("%s: %p: CON %08lx, DAT %08lx\n", __func__, base, con, dat);
116 
117         return 0;
118 }
119 
120 /* The next set of routines are for the case where the GPIO configuration
121  * registers are 4 bits per GPIO but there is more than one register (the
122  * bank has more than 8 GPIOs.
123  *
124  * This case is the similar to the 4 bit case, but the registers are as
125  * follows:
126  *
127  * base + 0x00: Control register, 4 bits per gpio (lower 8 GPIOs)
128  *              gpio n: 4 bits starting at (4*n)
129  *              0000 = input, 0001 = output, others mean special-function
130  * base + 0x04: Control register, 4 bits per gpio (up to 8 additions GPIOs)
131  *              gpio n: 4 bits starting at (4*n)
132  *              0000 = input, 0001 = output, others mean special-function
133  * base + 0x08: Data register, 1 bit per gpio
134  *              bit n: data bit n
135  *
136  * To allow us to use the s3c_gpiolib_get and s3c_gpiolib_set routines we
137  * store the 'base + 0x4' address so that these routines see the data
138  * register at ourchip->base + 0x04.
139 */
140 
141 static int s3c64xx_gpiolib_4bit2_input(struct gpio_chip *chip, unsigned offset)
142 {
143         struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip);
144         void __iomem *base = ourchip->base;
145         void __iomem *regcon = base;
146         unsigned long con;
147 
148         if (offset > 7)
149                 offset -= 8;
150         else
151                 regcon -= 4;
152 
153         con = __raw_readl(regcon);
154         con &= ~(0xf << con_4bit_shift(offset));
155         __raw_writel(con, regcon);
156 
157         gpio_dbg("%s: %p: CON %08lx\n", __func__, base, con);
158 
159         return 0;
160 
161 }
162 
163 static int s3c64xx_gpiolib_4bit2_output(struct gpio_chip *chip,
164                                        unsigned offset, int value)
165 {
166         struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip);
167         void __iomem *base = ourchip->base;
168         void __iomem *regcon = base;
169         unsigned long con;
170         unsigned long dat;
171 
172         if (offset > 7)
173                 offset -= 8;
174         else
175                 regcon -= 4;
176 
177         con = __raw_readl(regcon);
178         con &= ~(0xf << con_4bit_shift(offset));
179         con |= 0x1 << con_4bit_shift(offset);
180 
181         dat = __raw_readl(base + OFF_GPDAT);
182         if (value)
183                 dat |= 1 << offset;
184         else
185                 dat &= ~(1 << offset);
186 
187         __raw_writel(dat, base + OFF_GPDAT);
188         __raw_writel(con, regcon);
189         __raw_writel(dat, base + OFF_GPDAT);
190 
191         gpio_dbg("%s: %p: CON %08lx, DAT %08lx\n", __func__, base, con, dat);
192 
193         return 0;
194 }
195 
196 static struct s3c_gpio_cfg gpio_4bit_cfg_noint = {
197         .set_config     = s3c_gpio_setcfg_s3c64xx_4bit,
198         .set_pull       = s3c_gpio_setpull_updown,
199         .get_pull       = s3c_gpio_getpull_updown,
200 };
201 
202 static struct s3c_gpio_cfg gpio_4bit_cfg_eint0111 = {
203         .cfg_eint       = 7,
204         .set_config     = s3c_gpio_setcfg_s3c64xx_4bit,
205         .set_pull       = s3c_gpio_setpull_updown,
206         .get_pull       = s3c_gpio_getpull_updown,
207 };
208 
209 static struct s3c_gpio_cfg gpio_4bit_cfg_eint0011 = {
210         .cfg_eint       = 3,
211         .set_config     = s3c_gpio_setcfg_s3c64xx_4bit,
212         .set_pull       = s3c_gpio_setpull_updown,
213         .get_pull       = s3c_gpio_getpull_updown,
214 };
215 
216 static struct s3c_gpio_chip gpio_4bit[] = {
217         {
218                 .base   = S3C64XX_GPA_BASE,
219                 .config = &gpio_4bit_cfg_eint0111,
220                 .chip   = {
221                         .base   = S3C64XX_GPA(0),
222                         .ngpio  = S3C64XX_GPIO_A_NR,
223                         .label  = "GPA",
224                 },
225         }, {
226                 .base   = S3C64XX_GPB_BASE,
227                 .config = &gpio_4bit_cfg_eint0111,
228                 .chip   = {
229                         .base   = S3C64XX_GPB(0),
230                         .ngpio  = S3C64XX_GPIO_B_NR,
231                         .label  = "GPB",
232                 },
233         }, {
234                 .base   = S3C64XX_GPC_BASE,
235                 .config = &gpio_4bit_cfg_eint0111,
236                 .chip   = {
237                         .base   = S3C64XX_GPC(0),
238                         .ngpio  = S3C64XX_GPIO_C_NR,
239                         .label  = "GPC",
240                 },
241         }, {
242                 .base   = S3C64XX_GPD_BASE,
243                 .config = &gpio_4bit_cfg_eint0111,
244                 .chip   = {
245                         .base   = S3C64XX_GPD(0),
246                         .ngpio  = S3C64XX_GPIO_D_NR,
247                         .label  = "GPD",
248                 },
249         }, {
250                 .base   = S3C64XX_GPE_BASE,
251                 .config = &gpio_4bit_cfg_noint,
252                 .chip   = {
253                         .base   = S3C64XX_GPE(0),
254                         .ngpio  = S3C64XX_GPIO_E_NR,
255                         .label  = "GPE",
256                 },
257         }, {
258                 .base   = S3C64XX_GPG_BASE,
259                 .config = &gpio_4bit_cfg_eint0111,
260                 .chip   = {
261                         .base   = S3C64XX_GPG(0),
262                         .ngpio  = S3C64XX_GPIO_G_NR,
263                         .label  = "GPG",
264                 },
265         }, {
266                 .base   = S3C64XX_GPM_BASE,
267                 .config = &gpio_4bit_cfg_eint0011,
268                 .chip   = {
269                         .base   = S3C64XX_GPM(0),
270                         .ngpio  = S3C64XX_GPIO_M_NR,
271                         .label  = "GPM",
272                 },
273         },
274 };
275 
276 static struct s3c_gpio_chip gpio_4bit2[] = {
277         {
278                 .base   = S3C64XX_GPH_BASE + 0x4,
279                 .config = &gpio_4bit_cfg_eint0111,
280                 .chip   = {
281                         .base   = S3C64XX_GPH(0),
282                         .ngpio  = S3C64XX_GPIO_H_NR,
283                         .label  = "GPH",
284                 },
285         }, {
286                 .base   = S3C64XX_GPK_BASE + 0x4,
287                 .config = &gpio_4bit_cfg_noint,
288                 .chip   = {
289                         .base   = S3C64XX_GPK(0),
290                         .ngpio  = S3C64XX_GPIO_K_NR,
291                         .label  = "GPK",
292                 },
293         }, {
294                 .base   = S3C64XX_GPL_BASE + 0x4,
295                 .config = &gpio_4bit_cfg_eint0011,
296                 .chip   = {
297                         .base   = S3C64XX_GPL(0),
298                         .ngpio  = S3C64XX_GPIO_L_NR,
299                         .label  = "GPL",
300                 },
301         },
302 };
303 
304 static struct s3c_gpio_cfg gpio_2bit_cfg_noint = {
305         .set_config     = s3c_gpio_setcfg_s3c24xx,
306         .set_pull       = s3c_gpio_setpull_updown,
307         .get_pull       = s3c_gpio_getpull_updown,
308 };
309 
310 static struct s3c_gpio_cfg gpio_2bit_cfg_eint10 = {
311         .cfg_eint       = 2,
312         .set_config     = s3c_gpio_setcfg_s3c24xx,
313         .set_pull       = s3c_gpio_setpull_updown,
314         .get_pull       = s3c_gpio_getpull_updown,
315 };
316 
317 static struct s3c_gpio_cfg gpio_2bit_cfg_eint11 = {
318         .cfg_eint       = 3,
319         .set_config     = s3c_gpio_setcfg_s3c24xx,
320         .set_pull       = s3c_gpio_setpull_updown,
321         .get_pull       = s3c_gpio_getpull_updown,
322 };
323 
324 int s3c64xx_gpio2int_gpn(struct gpio_chip *chip, unsigned pin)
325 {
326         return IRQ_EINT(0) + pin;
327 }
328 
329 static struct s3c_gpio_chip gpio_2bit[] = {
330         {
331                 .base   = S3C64XX_GPF_BASE,
332                 .config = &gpio_2bit_cfg_eint11,
333                 .chip   = {
334                         .base   = S3C64XX_GPF(0),
335                         .ngpio  = S3C64XX_GPIO_F_NR,
336                         .label  = "GPF",
337                 },
338         }, {
339                 .base   = S3C64XX_GPI_BASE,
340                 .config = &gpio_2bit_cfg_noint,
341                 .chip   = {
342                         .base   = S3C64XX_GPI(0),
343                         .ngpio  = S3C64XX_GPIO_I_NR,
344                         .label  = "GPI",
345                 },
346         }, {
347                 .base   = S3C64XX_GPJ_BASE,
348                 .config = &gpio_2bit_cfg_noint,
349                 .chip   = {
350                         .base   = S3C64XX_GPJ(0),
351                         .ngpio  = S3C64XX_GPIO_J_NR,
352                         .label  = "GPJ",
353                 },
354         }, {
355                 .base   = S3C64XX_GPN_BASE,
356                 .config = &gpio_2bit_cfg_eint10,
357                 .chip   = {
358                         .base   = S3C64XX_GPN(0),
359                         .ngpio  = S3C64XX_GPIO_N_NR,
360                         .label  = "GPN",
361                         .to_irq = s3c64xx_gpio2int_gpn,
362                 },
363         }, {
364                 .base   = S3C64XX_GPO_BASE,
365                 .config = &gpio_2bit_cfg_eint11,
366                 .chip   = {
367                         .base   = S3C64XX_GPO(0),
368                         .ngpio  = S3C64XX_GPIO_O_NR,
369                         .label  = "GPO",
370                 },
371         }, {
372                 .base   = S3C64XX_GPP_BASE,
373                 .config = &gpio_2bit_cfg_eint11,
374                 .chip   = {
375                         .base   = S3C64XX_GPP(0),
376                         .ngpio  = S3C64XX_GPIO_P_NR,
377                         .label  = "GPP",
378                 },
379         }, {
380                 .base   = S3C64XX_GPQ_BASE,
381                 .config = &gpio_2bit_cfg_eint11,
382                 .chip   = {
383                         .base   = S3C64XX_GPQ(0),
384                         .ngpio  = S3C64XX_GPIO_Q_NR,
385                         .label  = "GPQ",
386                 },
387         },
388 };
389 
390 static __init void s3c64xx_gpiolib_add_4bit(struct s3c_gpio_chip *chip)
391 {
392         chip->chip.direction_input = s3c64xx_gpiolib_4bit_input;
393         chip->chip.direction_output = s3c64xx_gpiolib_4bit_output;
394         chip->pm = __gpio_pm(&s3c_gpio_pm_4bit);
395 }
396 
397 static __init void s3c64xx_gpiolib_add_4bit2(struct s3c_gpio_chip *chip)
398 {
399         chip->chip.direction_input = s3c64xx_gpiolib_4bit2_input;
400         chip->chip.direction_output = s3c64xx_gpiolib_4bit2_output;
401         chip->pm = __gpio_pm(&s3c_gpio_pm_4bit);
402 }
403 
404 static __init void s3c64xx_gpiolib_add_2bit(struct s3c_gpio_chip *chip)
405 {
406         chip->pm = __gpio_pm(&s3c_gpio_pm_2bit);
407 }
408 
409 static __init void s3c64xx_gpiolib_add(struct s3c_gpio_chip *chips,
410                                        int nr_chips,
411                                        void (*fn)(struct s3c_gpio_chip *))
412 {
413         for (; nr_chips > 0; nr_chips--, chips++) {
414                 if (fn)
415                         (fn)(chips);
416                 s3c_gpiolib_add(chips);
417         }
418 }
419 
420 static __init int s3c64xx_gpiolib_init(void)
421 {
422         s3c64xx_gpiolib_add(gpio_4bit, ARRAY_SIZE(gpio_4bit),
423                             s3c64xx_gpiolib_add_4bit);
424 
425         s3c64xx_gpiolib_add(gpio_4bit2, ARRAY_SIZE(gpio_4bit2),
426                             s3c64xx_gpiolib_add_4bit2);
427 
428         s3c64xx_gpiolib_add(gpio_2bit, ARRAY_SIZE(gpio_2bit),
429                             s3c64xx_gpiolib_add_2bit);
430 
431         return 0;
432 }
433 
434 core_initcall(s3c64xx_gpiolib_init);
435 

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

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | 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.

osdn.jp