diff options
author | Laxman Dewangan <ldewangan@nvidia.com> | 2013-09-03 10:28:03 -0400 |
---|---|---|
committer | Linus Walleij <linus.walleij@linaro.org> | 2013-09-19 09:31:48 -0400 |
commit | ca6af7b96ab621371f5f408e3fe7bd1e5cb063aa (patch) | |
tree | cdf4c99fb8f72b248eb9cb432a62cb70d92f636a /drivers | |
parent | 7b17b59feaa8b0a54a333005b87ad7ea804d021f (diff) |
gpio: palmas: add support for TPS80036
TI Palmas series device TPS80036 supports 16 GPIOs.
Register its all 16 gpios when this device is selected.
Signed-off-by: Laxman Dewangan <ldewangan@nvidia.com>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/gpio/gpio-palmas.c | 104 |
1 files changed, 69 insertions, 35 deletions
diff --git a/drivers/gpio/gpio-palmas.c b/drivers/gpio/gpio-palmas.c index 8588af0f7661..11801e986dd9 100644 --- a/drivers/gpio/gpio-palmas.c +++ b/drivers/gpio/gpio-palmas.c | |||
@@ -31,6 +31,10 @@ struct palmas_gpio { | |||
31 | struct palmas *palmas; | 31 | struct palmas *palmas; |
32 | }; | 32 | }; |
33 | 33 | ||
34 | struct palmas_device_data { | ||
35 | int ngpio; | ||
36 | }; | ||
37 | |||
34 | static inline struct palmas_gpio *to_palmas_gpio(struct gpio_chip *chip) | 38 | static inline struct palmas_gpio *to_palmas_gpio(struct gpio_chip *chip) |
35 | { | 39 | { |
36 | return container_of(chip, struct palmas_gpio, gpio_chip); | 40 | return container_of(chip, struct palmas_gpio, gpio_chip); |
@@ -42,23 +46,26 @@ static int palmas_gpio_get(struct gpio_chip *gc, unsigned offset) | |||
42 | struct palmas *palmas = pg->palmas; | 46 | struct palmas *palmas = pg->palmas; |
43 | unsigned int val; | 47 | unsigned int val; |
44 | int ret; | 48 | int ret; |
49 | unsigned int reg; | ||
50 | int gpio16 = (offset/8); | ||
51 | |||
52 | offset %= 8; | ||
53 | reg = (gpio16) ? PALMAS_GPIO_DATA_DIR2 : PALMAS_GPIO_DATA_DIR; | ||
45 | 54 | ||
46 | ret = palmas_read(palmas, PALMAS_GPIO_BASE, PALMAS_GPIO_DATA_DIR, &val); | 55 | ret = palmas_read(palmas, PALMAS_GPIO_BASE, reg, &val); |
47 | if (ret < 0) { | 56 | if (ret < 0) { |
48 | dev_err(gc->dev, "GPIO_DATA_DIR read failed, err = %d\n", ret); | 57 | dev_err(gc->dev, "Reg 0x%02x read failed, %d\n", reg, ret); |
49 | return ret; | 58 | return ret; |
50 | } | 59 | } |
51 | 60 | ||
52 | if (val & (1 << offset)) { | 61 | if (val & BIT(offset)) |
53 | ret = palmas_read(palmas, PALMAS_GPIO_BASE, | 62 | reg = (gpio16) ? PALMAS_GPIO_DATA_OUT2 : PALMAS_GPIO_DATA_OUT; |
54 | PALMAS_GPIO_DATA_OUT, &val); | 63 | else |
55 | } else { | 64 | reg = (gpio16) ? PALMAS_GPIO_DATA_IN2 : PALMAS_GPIO_DATA_IN; |
56 | ret = palmas_read(palmas, PALMAS_GPIO_BASE, | 65 | |
57 | PALMAS_GPIO_DATA_IN, &val); | 66 | ret = palmas_read(palmas, PALMAS_GPIO_BASE, reg, &val); |
58 | } | ||
59 | if (ret < 0) { | 67 | if (ret < 0) { |
60 | dev_err(gc->dev, "GPIO_DATA_IN/OUT read failed, err = %d\n", | 68 | dev_err(gc->dev, "Reg 0x%02x read failed, %d\n", reg, ret); |
61 | ret); | ||
62 | return ret; | 69 | return ret; |
63 | } | 70 | } |
64 | return !!(val & BIT(offset)); | 71 | return !!(val & BIT(offset)); |
@@ -70,17 +77,20 @@ static void palmas_gpio_set(struct gpio_chip *gc, unsigned offset, | |||
70 | struct palmas_gpio *pg = to_palmas_gpio(gc); | 77 | struct palmas_gpio *pg = to_palmas_gpio(gc); |
71 | struct palmas *palmas = pg->palmas; | 78 | struct palmas *palmas = pg->palmas; |
72 | int ret; | 79 | int ret; |
80 | unsigned int reg; | ||
81 | int gpio16 = (offset/8); | ||
73 | 82 | ||
74 | if (value) | 83 | offset %= 8; |
75 | ret = palmas_write(palmas, PALMAS_GPIO_BASE, | 84 | if (gpio16) |
76 | PALMAS_GPIO_SET_DATA_OUT, BIT(offset)); | 85 | reg = (value) ? |
86 | PALMAS_GPIO_SET_DATA_OUT2 : PALMAS_GPIO_CLEAR_DATA_OUT2; | ||
77 | else | 87 | else |
78 | ret = palmas_write(palmas, PALMAS_GPIO_BASE, | 88 | reg = (value) ? |
79 | PALMAS_GPIO_CLEAR_DATA_OUT, BIT(offset)); | 89 | PALMAS_GPIO_SET_DATA_OUT : PALMAS_GPIO_CLEAR_DATA_OUT; |
90 | |||
91 | ret = palmas_write(palmas, PALMAS_GPIO_BASE, reg, BIT(offset)); | ||
80 | if (ret < 0) | 92 | if (ret < 0) |
81 | dev_err(gc->dev, "%s write failed, err = %d\n", | 93 | dev_err(gc->dev, "Reg 0x%02x write failed, %d\n", reg, ret); |
82 | (value) ? "GPIO_SET_DATA_OUT" : "GPIO_CLEAR_DATA_OUT", | ||
83 | ret); | ||
84 | } | 94 | } |
85 | 95 | ||
86 | static int palmas_gpio_output(struct gpio_chip *gc, unsigned offset, | 96 | static int palmas_gpio_output(struct gpio_chip *gc, unsigned offset, |
@@ -89,14 +99,19 @@ static int palmas_gpio_output(struct gpio_chip *gc, unsigned offset, | |||
89 | struct palmas_gpio *pg = to_palmas_gpio(gc); | 99 | struct palmas_gpio *pg = to_palmas_gpio(gc); |
90 | struct palmas *palmas = pg->palmas; | 100 | struct palmas *palmas = pg->palmas; |
91 | int ret; | 101 | int ret; |
102 | unsigned int reg; | ||
103 | int gpio16 = (offset/8); | ||
104 | |||
105 | offset %= 8; | ||
106 | reg = (gpio16) ? PALMAS_GPIO_DATA_DIR2 : PALMAS_GPIO_DATA_DIR; | ||
92 | 107 | ||
93 | /* Set the initial value */ | 108 | /* Set the initial value */ |
94 | palmas_gpio_set(gc, offset, value); | 109 | palmas_gpio_set(gc, offset, value); |
95 | 110 | ||
96 | ret = palmas_update_bits(palmas, PALMAS_GPIO_BASE, | 111 | ret = palmas_update_bits(palmas, PALMAS_GPIO_BASE, reg, |
97 | PALMAS_GPIO_DATA_DIR, BIT(offset), BIT(offset)); | 112 | BIT(offset), BIT(offset)); |
98 | if (ret < 0) | 113 | if (ret < 0) |
99 | dev_err(gc->dev, "GPIO_DATA_DIR write failed, err = %d\n", ret); | 114 | dev_err(gc->dev, "Reg 0x%02x update failed, %d\n", reg, ret); |
100 | return ret; | 115 | return ret; |
101 | } | 116 | } |
102 | 117 | ||
@@ -105,11 +120,15 @@ static int palmas_gpio_input(struct gpio_chip *gc, unsigned offset) | |||
105 | struct palmas_gpio *pg = to_palmas_gpio(gc); | 120 | struct palmas_gpio *pg = to_palmas_gpio(gc); |
106 | struct palmas *palmas = pg->palmas; | 121 | struct palmas *palmas = pg->palmas; |
107 | int ret; | 122 | int ret; |
123 | unsigned int reg; | ||
124 | int gpio16 = (offset/8); | ||
125 | |||
126 | offset %= 8; | ||
127 | reg = (gpio16) ? PALMAS_GPIO_DATA_DIR2 : PALMAS_GPIO_DATA_DIR; | ||
108 | 128 | ||
109 | ret = palmas_update_bits(palmas, PALMAS_GPIO_BASE, | 129 | ret = palmas_update_bits(palmas, PALMAS_GPIO_BASE, reg, BIT(offset), 0); |
110 | PALMAS_GPIO_DATA_DIR, BIT(offset), 0); | ||
111 | if (ret < 0) | 130 | if (ret < 0) |
112 | dev_err(gc->dev, "GPIO_DATA_DIR write failed, err = %d\n", ret); | 131 | dev_err(gc->dev, "Reg 0x%02x update failed, %d\n", reg, ret); |
113 | return ret; | 132 | return ret; |
114 | } | 133 | } |
115 | 134 | ||
@@ -121,12 +140,36 @@ static int palmas_gpio_to_irq(struct gpio_chip *gc, unsigned offset) | |||
121 | return palmas_irq_get_virq(palmas, PALMAS_GPIO_0_IRQ + offset); | 140 | return palmas_irq_get_virq(palmas, PALMAS_GPIO_0_IRQ + offset); |
122 | } | 141 | } |
123 | 142 | ||
143 | static const struct palmas_device_data palmas_dev_data = { | ||
144 | .ngpio = 8, | ||
145 | }; | ||
146 | |||
147 | static const struct palmas_device_data tps80036_dev_data = { | ||
148 | .ngpio = 16, | ||
149 | }; | ||
150 | |||
151 | static struct of_device_id of_palmas_gpio_match[] = { | ||
152 | { .compatible = "ti,palmas-gpio", .data = &palmas_dev_data,}, | ||
153 | { .compatible = "ti,tps65913-gpio", .data = &palmas_dev_data,}, | ||
154 | { .compatible = "ti,tps65914-gpio", .data = &palmas_dev_data,}, | ||
155 | { .compatible = "ti,tps80036-gpio", .data = &tps80036_dev_data,}, | ||
156 | { }, | ||
157 | }; | ||
158 | MODULE_DEVICE_TABLE(of, of_palmas_gpio_match); | ||
159 | |||
124 | static int palmas_gpio_probe(struct platform_device *pdev) | 160 | static int palmas_gpio_probe(struct platform_device *pdev) |
125 | { | 161 | { |
126 | struct palmas *palmas = dev_get_drvdata(pdev->dev.parent); | 162 | struct palmas *palmas = dev_get_drvdata(pdev->dev.parent); |
127 | struct palmas_platform_data *palmas_pdata; | 163 | struct palmas_platform_data *palmas_pdata; |
128 | struct palmas_gpio *palmas_gpio; | 164 | struct palmas_gpio *palmas_gpio; |
129 | int ret; | 165 | int ret; |
166 | const struct of_device_id *match; | ||
167 | const struct palmas_device_data *dev_data; | ||
168 | |||
169 | match = of_match_device(of_palmas_gpio_match, &pdev->dev); | ||
170 | dev_data = match->data; | ||
171 | if (!dev_data) | ||
172 | dev_data = &palmas_dev_data; | ||
130 | 173 | ||
131 | palmas_gpio = devm_kzalloc(&pdev->dev, | 174 | palmas_gpio = devm_kzalloc(&pdev->dev, |
132 | sizeof(*palmas_gpio), GFP_KERNEL); | 175 | sizeof(*palmas_gpio), GFP_KERNEL); |
@@ -138,7 +181,7 @@ static int palmas_gpio_probe(struct platform_device *pdev) | |||
138 | palmas_gpio->palmas = palmas; | 181 | palmas_gpio->palmas = palmas; |
139 | palmas_gpio->gpio_chip.owner = THIS_MODULE; | 182 | palmas_gpio->gpio_chip.owner = THIS_MODULE; |
140 | palmas_gpio->gpio_chip.label = dev_name(&pdev->dev); | 183 | palmas_gpio->gpio_chip.label = dev_name(&pdev->dev); |
141 | palmas_gpio->gpio_chip.ngpio = 8; | 184 | palmas_gpio->gpio_chip.ngpio = dev_data->ngpio; |
142 | palmas_gpio->gpio_chip.can_sleep = 1; | 185 | palmas_gpio->gpio_chip.can_sleep = 1; |
143 | palmas_gpio->gpio_chip.direction_input = palmas_gpio_input; | 186 | palmas_gpio->gpio_chip.direction_input = palmas_gpio_input; |
144 | palmas_gpio->gpio_chip.direction_output = palmas_gpio_output; | 187 | palmas_gpio->gpio_chip.direction_output = palmas_gpio_output; |
@@ -172,15 +215,6 @@ static int palmas_gpio_remove(struct platform_device *pdev) | |||
172 | return gpiochip_remove(&palmas_gpio->gpio_chip); | 215 | return gpiochip_remove(&palmas_gpio->gpio_chip); |
173 | } | 216 | } |
174 | 217 | ||
175 | static struct of_device_id of_palmas_gpio_match[] = { | ||
176 | { .compatible = "ti,palmas-gpio"}, | ||
177 | { .compatible = "ti,tps65913-gpio"}, | ||
178 | { .compatible = "ti,tps65914-gpio"}, | ||
179 | { .compatible = "ti,tps80036-gpio"}, | ||
180 | { }, | ||
181 | }; | ||
182 | MODULE_DEVICE_TABLE(of, of_palmas_gpio_match); | ||
183 | |||
184 | static struct platform_driver palmas_gpio_driver = { | 218 | static struct platform_driver palmas_gpio_driver = { |
185 | .driver.name = "palmas-gpio", | 219 | .driver.name = "palmas-gpio", |
186 | .driver.owner = THIS_MODULE, | 220 | .driver.owner = THIS_MODULE, |