diff options
author | Alexander Shiyan <shc_work@mail.ru> | 2014-10-03 03:31:57 -0400 |
---|---|---|
committer | Linus Walleij <linus.walleij@linaro.org> | 2014-10-21 04:48:04 -0400 |
commit | af0a33e26c1f16a52fb2511400387a7eab9fe4d6 (patch) | |
tree | 681aeb53e3522433d9cde9f920f4b4b679ce35fe /drivers/gpio | |
parent | f114040e3ea6e07372334ade75d1ee0775c355e1 (diff) |
GPIO: Add driver for 74xx-ICs with MMIO access
This patch adds driver to support GPIO functionality for 74xx-compatible
ICs with MMIO access. Compatible models include:
1 bit: 741G125 (Input), 741G74 (Output)
2 bits: 742G125 (Input), 7474 (Output)
4 bits: 74125 (Input), 74175 (Output)
6 bits: 74365 (Input), 74174 (Output)
8 bits: 74244 (Input), 74273 (Output)
16 bits: 741624 (Input), 7416374 (Output)
Signed-off-by: Alexander Shiyan <shc_work@mail.ru>
Reviewed-by: Alexandre Courbot <acourbot@nvidia.com>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Diffstat (limited to 'drivers/gpio')
-rw-r--r-- | drivers/gpio/Kconfig | 14 | ||||
-rw-r--r-- | drivers/gpio/Makefile | 1 | ||||
-rw-r--r-- | drivers/gpio/gpio-74xx-mmio.c | 170 |
3 files changed, 185 insertions, 0 deletions
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 0959ca9b6b27..cd3313436b3a 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig | |||
@@ -112,6 +112,20 @@ config GPIO_MAX730X | |||
112 | 112 | ||
113 | comment "Memory mapped GPIO drivers:" | 113 | comment "Memory mapped GPIO drivers:" |
114 | 114 | ||
115 | config GPIO_74XX_MMIO | ||
116 | tristate "GPIO driver for 74xx-ICs with MMIO access" | ||
117 | depends on OF_GPIO | ||
118 | select GPIO_GENERIC | ||
119 | help | ||
120 | Say yes here to support GPIO functionality for 74xx-compatible ICs | ||
121 | with MMIO access. Compatible models include: | ||
122 | 1 bit: 741G125 (Input), 741G74 (Output) | ||
123 | 2 bits: 742G125 (Input), 7474 (Output) | ||
124 | 4 bits: 74125 (Input), 74175 (Output) | ||
125 | 6 bits: 74365 (Input), 74174 (Output) | ||
126 | 8 bits: 74244 (Input), 74273 (Output) | ||
127 | 16 bits: 741624 (Input), 7416374 (Output) | ||
128 | |||
115 | config GPIO_CLPS711X | 129 | config GPIO_CLPS711X |
116 | tristate "CLPS711X GPIO support" | 130 | tristate "CLPS711X GPIO support" |
117 | depends on ARCH_CLPS711X || COMPILE_TEST | 131 | depends on ARCH_CLPS711X || COMPILE_TEST |
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index e5d346cf3b6e..4486bbd2dad7 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile | |||
@@ -13,6 +13,7 @@ obj-$(CONFIG_GPIO_ACPI) += gpiolib-acpi.o | |||
13 | obj-$(CONFIG_GPIO_GENERIC) += gpio-generic.o | 13 | obj-$(CONFIG_GPIO_GENERIC) += gpio-generic.o |
14 | 14 | ||
15 | obj-$(CONFIG_GPIO_74X164) += gpio-74x164.o | 15 | obj-$(CONFIG_GPIO_74X164) += gpio-74x164.o |
16 | obj-$(CONFIG_GPIO_74XX_MMIO) += gpio-74xx-mmio.o | ||
16 | obj-$(CONFIG_GPIO_ADNP) += gpio-adnp.o | 17 | obj-$(CONFIG_GPIO_ADNP) += gpio-adnp.o |
17 | obj-$(CONFIG_GPIO_ADP5520) += gpio-adp5520.o | 18 | obj-$(CONFIG_GPIO_ADP5520) += gpio-adp5520.o |
18 | obj-$(CONFIG_GPIO_ADP5588) += gpio-adp5588.o | 19 | obj-$(CONFIG_GPIO_ADP5588) += gpio-adp5588.o |
diff --git a/drivers/gpio/gpio-74xx-mmio.c b/drivers/gpio/gpio-74xx-mmio.c new file mode 100644 index 000000000000..0763655cca6c --- /dev/null +++ b/drivers/gpio/gpio-74xx-mmio.c | |||
@@ -0,0 +1,170 @@ | |||
1 | /* | ||
2 | * 74xx MMIO GPIO driver | ||
3 | * | ||
4 | * Copyright (C) 2014 Alexander Shiyan <shc_work@mail.ru> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | */ | ||
11 | |||
12 | #include <linux/err.h> | ||
13 | #include <linux/gpio.h> | ||
14 | #include <linux/module.h> | ||
15 | #include <linux/of_device.h> | ||
16 | #include <linux/basic_mmio_gpio.h> | ||
17 | #include <linux/platform_device.h> | ||
18 | |||
19 | #define MMIO_74XX_DIR_IN (0 << 8) | ||
20 | #define MMIO_74XX_DIR_OUT (1 << 8) | ||
21 | #define MMIO_74XX_BIT_CNT(x) ((x) & 0xff) | ||
22 | |||
23 | struct mmio_74xx_gpio_priv { | ||
24 | struct bgpio_chip bgc; | ||
25 | unsigned flags; | ||
26 | }; | ||
27 | |||
28 | static const struct of_device_id mmio_74xx_gpio_ids[] = { | ||
29 | { | ||
30 | .compatible = "ti,741g125", | ||
31 | .data = (const void *)(MMIO_74XX_DIR_IN | 1), | ||
32 | }, | ||
33 | { | ||
34 | .compatible = "ti,742g125", | ||
35 | .data = (const void *)(MMIO_74XX_DIR_IN | 2), | ||
36 | }, | ||
37 | { | ||
38 | .compatible = "ti,74125", | ||
39 | .data = (const void *)(MMIO_74XX_DIR_IN | 4), | ||
40 | }, | ||
41 | { | ||
42 | .compatible = "ti,74365", | ||
43 | .data = (const void *)(MMIO_74XX_DIR_IN | 6), | ||
44 | }, | ||
45 | { | ||
46 | .compatible = "ti,74244", | ||
47 | .data = (const void *)(MMIO_74XX_DIR_IN | 8), | ||
48 | }, | ||
49 | { | ||
50 | .compatible = "ti,741624", | ||
51 | .data = (const void *)(MMIO_74XX_DIR_IN | 16), | ||
52 | }, | ||
53 | { | ||
54 | .compatible = "ti,741g74", | ||
55 | .data = (const void *)(MMIO_74XX_DIR_OUT | 1), | ||
56 | }, | ||
57 | { | ||
58 | .compatible = "ti,7474", | ||
59 | .data = (const void *)(MMIO_74XX_DIR_OUT | 2), | ||
60 | }, | ||
61 | { | ||
62 | .compatible = "ti,74175", | ||
63 | .data = (const void *)(MMIO_74XX_DIR_OUT | 4), | ||
64 | }, | ||
65 | { | ||
66 | .compatible = "ti,74174", | ||
67 | .data = (const void *)(MMIO_74XX_DIR_OUT | 6), | ||
68 | }, | ||
69 | { | ||
70 | .compatible = "ti,74273", | ||
71 | .data = (const void *)(MMIO_74XX_DIR_OUT | 8), | ||
72 | }, | ||
73 | { | ||
74 | .compatible = "ti,7416374", | ||
75 | .data = (const void *)(MMIO_74XX_DIR_OUT | 16), | ||
76 | }, | ||
77 | { } | ||
78 | }; | ||
79 | MODULE_DEVICE_TABLE(of, mmio_74xx_gpio_ids); | ||
80 | |||
81 | static inline struct mmio_74xx_gpio_priv *to_74xx_gpio(struct gpio_chip *gc) | ||
82 | { | ||
83 | struct bgpio_chip *bgc = to_bgpio_chip(gc); | ||
84 | |||
85 | return container_of(bgc, struct mmio_74xx_gpio_priv, bgc); | ||
86 | } | ||
87 | |||
88 | static int mmio_74xx_get_direction(struct gpio_chip *gc, unsigned offset) | ||
89 | { | ||
90 | struct mmio_74xx_gpio_priv *priv = to_74xx_gpio(gc); | ||
91 | |||
92 | return (priv->flags & MMIO_74XX_DIR_OUT) ? GPIOF_DIR_OUT : GPIOF_DIR_IN; | ||
93 | } | ||
94 | |||
95 | static int mmio_74xx_dir_in(struct gpio_chip *gc, unsigned int gpio) | ||
96 | { | ||
97 | struct mmio_74xx_gpio_priv *priv = to_74xx_gpio(gc); | ||
98 | |||
99 | return (priv->flags & MMIO_74XX_DIR_OUT) ? -ENOTSUPP : 0; | ||
100 | } | ||
101 | |||
102 | static int mmio_74xx_dir_out(struct gpio_chip *gc, unsigned int gpio, int val) | ||
103 | { | ||
104 | struct mmio_74xx_gpio_priv *priv = to_74xx_gpio(gc); | ||
105 | |||
106 | if (priv->flags & MMIO_74XX_DIR_OUT) { | ||
107 | gc->set(gc, gpio, val); | ||
108 | return 0; | ||
109 | } | ||
110 | |||
111 | return -ENOTSUPP; | ||
112 | } | ||
113 | |||
114 | static int mmio_74xx_gpio_probe(struct platform_device *pdev) | ||
115 | { | ||
116 | const struct of_device_id *of_id = | ||
117 | of_match_device(mmio_74xx_gpio_ids, &pdev->dev); | ||
118 | struct mmio_74xx_gpio_priv *priv; | ||
119 | struct resource *res; | ||
120 | void __iomem *dat; | ||
121 | int err; | ||
122 | |||
123 | priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); | ||
124 | if (!priv) | ||
125 | return -ENOMEM; | ||
126 | |||
127 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
128 | dat = devm_ioremap_resource(&pdev->dev, res); | ||
129 | if (IS_ERR(dat)) | ||
130 | return PTR_ERR(dat); | ||
131 | |||
132 | priv->flags = (unsigned)of_id->data; | ||
133 | |||
134 | err = bgpio_init(&priv->bgc, &pdev->dev, | ||
135 | DIV_ROUND_UP(MMIO_74XX_BIT_CNT(priv->flags), 8), | ||
136 | dat, NULL, NULL, NULL, NULL, 0); | ||
137 | if (err) | ||
138 | return err; | ||
139 | |||
140 | priv->bgc.gc.direction_input = mmio_74xx_dir_in; | ||
141 | priv->bgc.gc.direction_output = mmio_74xx_dir_out; | ||
142 | priv->bgc.gc.get_direction = mmio_74xx_get_direction; | ||
143 | priv->bgc.gc.ngpio = MMIO_74XX_BIT_CNT(priv->flags); | ||
144 | priv->bgc.gc.owner = THIS_MODULE; | ||
145 | |||
146 | platform_set_drvdata(pdev, priv); | ||
147 | |||
148 | return gpiochip_add(&priv->bgc.gc); | ||
149 | } | ||
150 | |||
151 | static int mmio_74xx_gpio_remove(struct platform_device *pdev) | ||
152 | { | ||
153 | struct mmio_74xx_gpio_priv *priv = platform_get_drvdata(pdev); | ||
154 | |||
155 | return bgpio_remove(&priv->bgc); | ||
156 | } | ||
157 | |||
158 | static struct platform_driver mmio_74xx_gpio_driver = { | ||
159 | .driver = { | ||
160 | .name = "74xx-mmio-gpio", | ||
161 | .of_match_table = mmio_74xx_gpio_ids, | ||
162 | }, | ||
163 | .probe = mmio_74xx_gpio_probe, | ||
164 | .remove = mmio_74xx_gpio_remove, | ||
165 | }; | ||
166 | module_platform_driver(mmio_74xx_gpio_driver); | ||
167 | |||
168 | MODULE_LICENSE("GPL"); | ||
169 | MODULE_AUTHOR("Alexander Shiyan <shc_work@mail.ru>"); | ||
170 | MODULE_DESCRIPTION("74xx MMIO GPIO driver"); | ||