Blame view
drivers/gpio/gpio-tc3589x.c
9.62 KB
d88b25be3 gpio: Add TC35892... |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
/* * Copyright (C) ST-Ericsson SA 2010 * * License Terms: GNU General Public License, version 2 * Author: Hanumath Prasad <hanumath.prasad@stericsson.com> for ST-Ericsson * Author: Rabin Vincent <rabin.vincent@stericsson.com> for ST-Ericsson */ #include <linux/module.h> #include <linux/init.h> #include <linux/platform_device.h> #include <linux/slab.h> #include <linux/gpio.h> #include <linux/irq.h> #include <linux/interrupt.h> |
c6eda6c5e mfd/tc35892: rena... |
16 |
#include <linux/mfd/tc3589x.h> |
d88b25be3 gpio: Add TC35892... |
17 18 19 20 21 22 23 24 25 |
/* * These registers are modified under the irq bus lock and cached to avoid * unnecessary writes in bus_sync_unlock. */ enum { REG_IBE, REG_IEV, REG_IS, REG_IE }; #define CACHE_NR_REGS 4 #define CACHE_NR_BANKS 3 |
20406ebff mfd/tc3589x: rena... |
26 |
struct tc3589x_gpio { |
d88b25be3 gpio: Add TC35892... |
27 |
struct gpio_chip chip; |
20406ebff mfd/tc3589x: rena... |
28 |
struct tc3589x *tc3589x; |
d88b25be3 gpio: Add TC35892... |
29 30 31 32 33 34 35 36 37 |
struct device *dev; struct mutex irq_lock; int irq_base; /* Caches of interrupt control registers for bus_lock */ u8 regs[CACHE_NR_REGS][CACHE_NR_BANKS]; u8 oldregs[CACHE_NR_REGS][CACHE_NR_BANKS]; }; |
20406ebff mfd/tc3589x: rena... |
38 |
static inline struct tc3589x_gpio *to_tc3589x_gpio(struct gpio_chip *chip) |
d88b25be3 gpio: Add TC35892... |
39 |
{ |
20406ebff mfd/tc3589x: rena... |
40 |
return container_of(chip, struct tc3589x_gpio, chip); |
d88b25be3 gpio: Add TC35892... |
41 |
} |
20406ebff mfd/tc3589x: rena... |
42 |
static int tc3589x_gpio_get(struct gpio_chip *chip, unsigned offset) |
d88b25be3 gpio: Add TC35892... |
43 |
{ |
20406ebff mfd/tc3589x: rena... |
44 45 46 |
struct tc3589x_gpio *tc3589x_gpio = to_tc3589x_gpio(chip); struct tc3589x *tc3589x = tc3589x_gpio->tc3589x; u8 reg = TC3589x_GPIODATA0 + (offset / 8) * 2; |
d88b25be3 gpio: Add TC35892... |
47 48 |
u8 mask = 1 << (offset % 8); int ret; |
20406ebff mfd/tc3589x: rena... |
49 |
ret = tc3589x_reg_read(tc3589x, reg); |
d88b25be3 gpio: Add TC35892... |
50 51 52 53 54 |
if (ret < 0) return ret; return ret & mask; } |
20406ebff mfd/tc3589x: rena... |
55 |
static void tc3589x_gpio_set(struct gpio_chip *chip, unsigned offset, int val) |
d88b25be3 gpio: Add TC35892... |
56 |
{ |
20406ebff mfd/tc3589x: rena... |
57 58 59 |
struct tc3589x_gpio *tc3589x_gpio = to_tc3589x_gpio(chip); struct tc3589x *tc3589x = tc3589x_gpio->tc3589x; u8 reg = TC3589x_GPIODATA0 + (offset / 8) * 2; |
d88b25be3 gpio: Add TC35892... |
60 61 |
unsigned pos = offset % 8; u8 data[] = {!!val << pos, 1 << pos}; |
20406ebff mfd/tc3589x: rena... |
62 |
tc3589x_block_write(tc3589x, reg, ARRAY_SIZE(data), data); |
d88b25be3 gpio: Add TC35892... |
63 |
} |
20406ebff mfd/tc3589x: rena... |
64 |
static int tc3589x_gpio_direction_output(struct gpio_chip *chip, |
d88b25be3 gpio: Add TC35892... |
65 66 |
unsigned offset, int val) { |
20406ebff mfd/tc3589x: rena... |
67 68 69 |
struct tc3589x_gpio *tc3589x_gpio = to_tc3589x_gpio(chip); struct tc3589x *tc3589x = tc3589x_gpio->tc3589x; u8 reg = TC3589x_GPIODIR0 + offset / 8; |
d88b25be3 gpio: Add TC35892... |
70 |
unsigned pos = offset % 8; |
20406ebff mfd/tc3589x: rena... |
71 |
tc3589x_gpio_set(chip, offset, val); |
d88b25be3 gpio: Add TC35892... |
72 |
|
20406ebff mfd/tc3589x: rena... |
73 |
return tc3589x_set_bits(tc3589x, reg, 1 << pos, 1 << pos); |
d88b25be3 gpio: Add TC35892... |
74 |
} |
20406ebff mfd/tc3589x: rena... |
75 |
static int tc3589x_gpio_direction_input(struct gpio_chip *chip, |
d88b25be3 gpio: Add TC35892... |
76 77 |
unsigned offset) { |
20406ebff mfd/tc3589x: rena... |
78 79 80 |
struct tc3589x_gpio *tc3589x_gpio = to_tc3589x_gpio(chip); struct tc3589x *tc3589x = tc3589x_gpio->tc3589x; u8 reg = TC3589x_GPIODIR0 + offset / 8; |
d88b25be3 gpio: Add TC35892... |
81 |
unsigned pos = offset % 8; |
20406ebff mfd/tc3589x: rena... |
82 |
return tc3589x_set_bits(tc3589x, reg, 1 << pos, 0); |
d88b25be3 gpio: Add TC35892... |
83 |
} |
20406ebff mfd/tc3589x: rena... |
84 |
static int tc3589x_gpio_to_irq(struct gpio_chip *chip, unsigned offset) |
d88b25be3 gpio: Add TC35892... |
85 |
{ |
20406ebff mfd/tc3589x: rena... |
86 |
struct tc3589x_gpio *tc3589x_gpio = to_tc3589x_gpio(chip); |
d88b25be3 gpio: Add TC35892... |
87 |
|
20406ebff mfd/tc3589x: rena... |
88 |
return tc3589x_gpio->irq_base + offset; |
d88b25be3 gpio: Add TC35892... |
89 90 91 |
} static struct gpio_chip template_chip = { |
20406ebff mfd/tc3589x: rena... |
92 |
.label = "tc3589x", |
d88b25be3 gpio: Add TC35892... |
93 |
.owner = THIS_MODULE, |
20406ebff mfd/tc3589x: rena... |
94 95 96 97 98 |
.direction_input = tc3589x_gpio_direction_input, .get = tc3589x_gpio_get, .direction_output = tc3589x_gpio_direction_output, .set = tc3589x_gpio_set, .to_irq = tc3589x_gpio_to_irq, |
d88b25be3 gpio: Add TC35892... |
99 100 |
.can_sleep = 1, }; |
33fcc1b80 gpio: tc35892-gpi... |
101 |
static int tc3589x_gpio_irq_set_type(struct irq_data *d, unsigned int type) |
d88b25be3 gpio: Add TC35892... |
102 |
{ |
33fcc1b80 gpio: tc35892-gpi... |
103 104 |
struct tc3589x_gpio *tc3589x_gpio = irq_data_get_irq_chip_data(d); int offset = d->irq - tc3589x_gpio->irq_base; |
d88b25be3 gpio: Add TC35892... |
105 106 107 108 |
int regoffset = offset / 8; int mask = 1 << (offset % 8); if (type == IRQ_TYPE_EDGE_BOTH) { |
20406ebff mfd/tc3589x: rena... |
109 |
tc3589x_gpio->regs[REG_IBE][regoffset] |= mask; |
d88b25be3 gpio: Add TC35892... |
110 111 |
return 0; } |
20406ebff mfd/tc3589x: rena... |
112 |
tc3589x_gpio->regs[REG_IBE][regoffset] &= ~mask; |
d88b25be3 gpio: Add TC35892... |
113 114 |
if (type == IRQ_TYPE_LEVEL_LOW || type == IRQ_TYPE_LEVEL_HIGH) |
20406ebff mfd/tc3589x: rena... |
115 |
tc3589x_gpio->regs[REG_IS][regoffset] |= mask; |
d88b25be3 gpio: Add TC35892... |
116 |
else |
20406ebff mfd/tc3589x: rena... |
117 |
tc3589x_gpio->regs[REG_IS][regoffset] &= ~mask; |
d88b25be3 gpio: Add TC35892... |
118 119 |
if (type == IRQ_TYPE_EDGE_RISING || type == IRQ_TYPE_LEVEL_HIGH) |
20406ebff mfd/tc3589x: rena... |
120 |
tc3589x_gpio->regs[REG_IEV][regoffset] |= mask; |
d88b25be3 gpio: Add TC35892... |
121 |
else |
20406ebff mfd/tc3589x: rena... |
122 |
tc3589x_gpio->regs[REG_IEV][regoffset] &= ~mask; |
d88b25be3 gpio: Add TC35892... |
123 124 125 |
return 0; } |
33fcc1b80 gpio: tc35892-gpi... |
126 |
static void tc3589x_gpio_irq_lock(struct irq_data *d) |
d88b25be3 gpio: Add TC35892... |
127 |
{ |
33fcc1b80 gpio: tc35892-gpi... |
128 |
struct tc3589x_gpio *tc3589x_gpio = irq_data_get_irq_chip_data(d); |
d88b25be3 gpio: Add TC35892... |
129 |
|
20406ebff mfd/tc3589x: rena... |
130 |
mutex_lock(&tc3589x_gpio->irq_lock); |
d88b25be3 gpio: Add TC35892... |
131 |
} |
33fcc1b80 gpio: tc35892-gpi... |
132 |
static void tc3589x_gpio_irq_sync_unlock(struct irq_data *d) |
d88b25be3 gpio: Add TC35892... |
133 |
{ |
33fcc1b80 gpio: tc35892-gpi... |
134 |
struct tc3589x_gpio *tc3589x_gpio = irq_data_get_irq_chip_data(d); |
20406ebff mfd/tc3589x: rena... |
135 |
struct tc3589x *tc3589x = tc3589x_gpio->tc3589x; |
d88b25be3 gpio: Add TC35892... |
136 |
static const u8 regmap[] = { |
20406ebff mfd/tc3589x: rena... |
137 138 139 140 |
[REG_IBE] = TC3589x_GPIOIBE0, [REG_IEV] = TC3589x_GPIOIEV0, [REG_IS] = TC3589x_GPIOIS0, [REG_IE] = TC3589x_GPIOIE0, |
d88b25be3 gpio: Add TC35892... |
141 142 143 144 145 |
}; int i, j; for (i = 0; i < CACHE_NR_REGS; i++) { for (j = 0; j < CACHE_NR_BANKS; j++) { |
20406ebff mfd/tc3589x: rena... |
146 147 |
u8 old = tc3589x_gpio->oldregs[i][j]; u8 new = tc3589x_gpio->regs[i][j]; |
d88b25be3 gpio: Add TC35892... |
148 149 150 |
if (new == old) continue; |
20406ebff mfd/tc3589x: rena... |
151 152 |
tc3589x_gpio->oldregs[i][j] = new; tc3589x_reg_write(tc3589x, regmap[i] + j * 8, new); |
d88b25be3 gpio: Add TC35892... |
153 154 |
} } |
20406ebff mfd/tc3589x: rena... |
155 |
mutex_unlock(&tc3589x_gpio->irq_lock); |
d88b25be3 gpio: Add TC35892... |
156 |
} |
33fcc1b80 gpio: tc35892-gpi... |
157 |
static void tc3589x_gpio_irq_mask(struct irq_data *d) |
d88b25be3 gpio: Add TC35892... |
158 |
{ |
33fcc1b80 gpio: tc35892-gpi... |
159 160 |
struct tc3589x_gpio *tc3589x_gpio = irq_data_get_irq_chip_data(d); int offset = d->irq - tc3589x_gpio->irq_base; |
d88b25be3 gpio: Add TC35892... |
161 162 |
int regoffset = offset / 8; int mask = 1 << (offset % 8); |
20406ebff mfd/tc3589x: rena... |
163 |
tc3589x_gpio->regs[REG_IE][regoffset] &= ~mask; |
d88b25be3 gpio: Add TC35892... |
164 |
} |
33fcc1b80 gpio: tc35892-gpi... |
165 |
static void tc3589x_gpio_irq_unmask(struct irq_data *d) |
d88b25be3 gpio: Add TC35892... |
166 |
{ |
33fcc1b80 gpio: tc35892-gpi... |
167 168 |
struct tc3589x_gpio *tc3589x_gpio = irq_data_get_irq_chip_data(d); int offset = d->irq - tc3589x_gpio->irq_base; |
d88b25be3 gpio: Add TC35892... |
169 170 |
int regoffset = offset / 8; int mask = 1 << (offset % 8); |
20406ebff mfd/tc3589x: rena... |
171 |
tc3589x_gpio->regs[REG_IE][regoffset] |= mask; |
d88b25be3 gpio: Add TC35892... |
172 |
} |
20406ebff mfd/tc3589x: rena... |
173 174 |
static struct irq_chip tc3589x_gpio_irq_chip = { .name = "tc3589x-gpio", |
33fcc1b80 gpio: tc35892-gpi... |
175 176 177 178 179 |
.irq_bus_lock = tc3589x_gpio_irq_lock, .irq_bus_sync_unlock = tc3589x_gpio_irq_sync_unlock, .irq_mask = tc3589x_gpio_irq_mask, .irq_unmask = tc3589x_gpio_irq_unmask, .irq_set_type = tc3589x_gpio_irq_set_type, |
d88b25be3 gpio: Add TC35892... |
180 |
}; |
20406ebff mfd/tc3589x: rena... |
181 |
static irqreturn_t tc3589x_gpio_irq(int irq, void *dev) |
d88b25be3 gpio: Add TC35892... |
182 |
{ |
20406ebff mfd/tc3589x: rena... |
183 184 |
struct tc3589x_gpio *tc3589x_gpio = dev; struct tc3589x *tc3589x = tc3589x_gpio->tc3589x; |
d88b25be3 gpio: Add TC35892... |
185 186 187 |
u8 status[CACHE_NR_BANKS]; int ret; int i; |
20406ebff mfd/tc3589x: rena... |
188 |
ret = tc3589x_block_read(tc3589x, TC3589x_GPIOMIS0, |
d88b25be3 gpio: Add TC35892... |
189 190 191 192 193 194 195 196 197 198 199 200 |
ARRAY_SIZE(status), status); if (ret < 0) return IRQ_NONE; for (i = 0; i < ARRAY_SIZE(status); i++) { unsigned int stat = status[i]; if (!stat) continue; while (stat) { int bit = __ffs(stat); int line = i * 8 + bit; |
20406ebff mfd/tc3589x: rena... |
201 |
handle_nested_irq(tc3589x_gpio->irq_base + line); |
d88b25be3 gpio: Add TC35892... |
202 203 |
stat &= ~(1 << bit); } |
20406ebff mfd/tc3589x: rena... |
204 |
tc3589x_reg_write(tc3589x, TC3589x_GPIOIC0 + i, status[i]); |
d88b25be3 gpio: Add TC35892... |
205 206 207 208 |
} return IRQ_HANDLED; } |
20406ebff mfd/tc3589x: rena... |
209 |
static int tc3589x_gpio_irq_init(struct tc3589x_gpio *tc3589x_gpio) |
d88b25be3 gpio: Add TC35892... |
210 |
{ |
20406ebff mfd/tc3589x: rena... |
211 |
int base = tc3589x_gpio->irq_base; |
d88b25be3 gpio: Add TC35892... |
212 |
int irq; |
20406ebff mfd/tc3589x: rena... |
213 |
for (irq = base; irq < base + tc3589x_gpio->chip.ngpio; irq++) { |
b51804bcf gpio: Cleanup gen... |
214 215 |
irq_set_chip_data(irq, tc3589x_gpio); irq_set_chip_and_handler(irq, &tc3589x_gpio_irq_chip, |
d88b25be3 gpio: Add TC35892... |
216 |
handle_simple_irq); |
b51804bcf gpio: Cleanup gen... |
217 |
irq_set_nested_thread(irq, 1); |
d88b25be3 gpio: Add TC35892... |
218 219 220 |
#ifdef CONFIG_ARM set_irq_flags(irq, IRQF_VALID); #else |
b51804bcf gpio: Cleanup gen... |
221 |
irq_set_noprobe(irq); |
d88b25be3 gpio: Add TC35892... |
222 223 224 225 226 |
#endif } return 0; } |
20406ebff mfd/tc3589x: rena... |
227 |
static void tc3589x_gpio_irq_remove(struct tc3589x_gpio *tc3589x_gpio) |
d88b25be3 gpio: Add TC35892... |
228 |
{ |
20406ebff mfd/tc3589x: rena... |
229 |
int base = tc3589x_gpio->irq_base; |
d88b25be3 gpio: Add TC35892... |
230 |
int irq; |
20406ebff mfd/tc3589x: rena... |
231 |
for (irq = base; irq < base + tc3589x_gpio->chip.ngpio; irq++) { |
d88b25be3 gpio: Add TC35892... |
232 233 234 |
#ifdef CONFIG_ARM set_irq_flags(irq, 0); #endif |
b51804bcf gpio: Cleanup gen... |
235 236 |
irq_set_chip_and_handler(irq, NULL, NULL); irq_set_chip_data(irq, NULL); |
d88b25be3 gpio: Add TC35892... |
237 238 |
} } |
20406ebff mfd/tc3589x: rena... |
239 |
static int __devinit tc3589x_gpio_probe(struct platform_device *pdev) |
d88b25be3 gpio: Add TC35892... |
240 |
{ |
20406ebff mfd/tc3589x: rena... |
241 242 243 |
struct tc3589x *tc3589x = dev_get_drvdata(pdev->dev.parent); struct tc3589x_gpio_platform_data *pdata; struct tc3589x_gpio *tc3589x_gpio; |
d88b25be3 gpio: Add TC35892... |
244 245 |
int ret; int irq; |
20406ebff mfd/tc3589x: rena... |
246 |
pdata = tc3589x->pdata->gpio; |
d88b25be3 gpio: Add TC35892... |
247 248 249 250 251 252 |
if (!pdata) return -ENODEV; irq = platform_get_irq(pdev, 0); if (irq < 0) return irq; |
20406ebff mfd/tc3589x: rena... |
253 254 |
tc3589x_gpio = kzalloc(sizeof(struct tc3589x_gpio), GFP_KERNEL); if (!tc3589x_gpio) |
d88b25be3 gpio: Add TC35892... |
255 |
return -ENOMEM; |
20406ebff mfd/tc3589x: rena... |
256 |
mutex_init(&tc3589x_gpio->irq_lock); |
d88b25be3 gpio: Add TC35892... |
257 |
|
20406ebff mfd/tc3589x: rena... |
258 259 |
tc3589x_gpio->dev = &pdev->dev; tc3589x_gpio->tc3589x = tc3589x; |
d88b25be3 gpio: Add TC35892... |
260 |
|
20406ebff mfd/tc3589x: rena... |
261 262 263 264 |
tc3589x_gpio->chip = template_chip; tc3589x_gpio->chip.ngpio = tc3589x->num_gpio; tc3589x_gpio->chip.dev = &pdev->dev; tc3589x_gpio->chip.base = pdata->gpio_base; |
d88b25be3 gpio: Add TC35892... |
265 |
|
20406ebff mfd/tc3589x: rena... |
266 |
tc3589x_gpio->irq_base = tc3589x->irq_base + TC3589x_INT_GPIO(0); |
d88b25be3 gpio: Add TC35892... |
267 268 |
/* Bring the GPIO module out of reset */ |
20406ebff mfd/tc3589x: rena... |
269 270 |
ret = tc3589x_set_bits(tc3589x, TC3589x_RSTCTRL, TC3589x_RSTCTRL_GPIRST, 0); |
d88b25be3 gpio: Add TC35892... |
271 272 |
if (ret < 0) goto out_free; |
20406ebff mfd/tc3589x: rena... |
273 |
ret = tc3589x_gpio_irq_init(tc3589x_gpio); |
d88b25be3 gpio: Add TC35892... |
274 275 |
if (ret) goto out_free; |
20406ebff mfd/tc3589x: rena... |
276 277 |
ret = request_threaded_irq(irq, NULL, tc3589x_gpio_irq, IRQF_ONESHOT, "tc3589x-gpio", tc3589x_gpio); |
d88b25be3 gpio: Add TC35892... |
278 279 280 281 282 |
if (ret) { dev_err(&pdev->dev, "unable to get irq: %d ", ret); goto out_removeirq; } |
20406ebff mfd/tc3589x: rena... |
283 |
ret = gpiochip_add(&tc3589x_gpio->chip); |
d88b25be3 gpio: Add TC35892... |
284 285 286 287 288 |
if (ret) { dev_err(&pdev->dev, "unable to add gpiochip: %d ", ret); goto out_freeirq; } |
f0a7a98d1 ARM: 6373/1: tc35... |
289 |
if (pdata->setup) |
20406ebff mfd/tc3589x: rena... |
290 |
pdata->setup(tc3589x, tc3589x_gpio->chip.base); |
f0a7a98d1 ARM: 6373/1: tc35... |
291 |
|
20406ebff mfd/tc3589x: rena... |
292 |
platform_set_drvdata(pdev, tc3589x_gpio); |
d88b25be3 gpio: Add TC35892... |
293 294 295 296 |
return 0; out_freeirq: |
20406ebff mfd/tc3589x: rena... |
297 |
free_irq(irq, tc3589x_gpio); |
d88b25be3 gpio: Add TC35892... |
298 |
out_removeirq: |
20406ebff mfd/tc3589x: rena... |
299 |
tc3589x_gpio_irq_remove(tc3589x_gpio); |
d88b25be3 gpio: Add TC35892... |
300 |
out_free: |
20406ebff mfd/tc3589x: rena... |
301 |
kfree(tc3589x_gpio); |
d88b25be3 gpio: Add TC35892... |
302 303 |
return ret; } |
20406ebff mfd/tc3589x: rena... |
304 |
static int __devexit tc3589x_gpio_remove(struct platform_device *pdev) |
d88b25be3 gpio: Add TC35892... |
305 |
{ |
20406ebff mfd/tc3589x: rena... |
306 307 308 |
struct tc3589x_gpio *tc3589x_gpio = platform_get_drvdata(pdev); struct tc3589x *tc3589x = tc3589x_gpio->tc3589x; struct tc3589x_gpio_platform_data *pdata = tc3589x->pdata->gpio; |
d88b25be3 gpio: Add TC35892... |
309 310 |
int irq = platform_get_irq(pdev, 0); int ret; |
f0a7a98d1 ARM: 6373/1: tc35... |
311 |
if (pdata->remove) |
20406ebff mfd/tc3589x: rena... |
312 |
pdata->remove(tc3589x, tc3589x_gpio->chip.base); |
f0a7a98d1 ARM: 6373/1: tc35... |
313 |
|
20406ebff mfd/tc3589x: rena... |
314 |
ret = gpiochip_remove(&tc3589x_gpio->chip); |
d88b25be3 gpio: Add TC35892... |
315 |
if (ret < 0) { |
20406ebff mfd/tc3589x: rena... |
316 |
dev_err(tc3589x_gpio->dev, |
d88b25be3 gpio: Add TC35892... |
317 318 319 320 |
"unable to remove gpiochip: %d ", ret); return ret; } |
20406ebff mfd/tc3589x: rena... |
321 322 |
free_irq(irq, tc3589x_gpio); tc3589x_gpio_irq_remove(tc3589x_gpio); |
d88b25be3 gpio: Add TC35892... |
323 324 |
platform_set_drvdata(pdev, NULL); |
20406ebff mfd/tc3589x: rena... |
325 |
kfree(tc3589x_gpio); |
d88b25be3 gpio: Add TC35892... |
326 327 328 |
return 0; } |
20406ebff mfd/tc3589x: rena... |
329 330 |
static struct platform_driver tc3589x_gpio_driver = { .driver.name = "tc3589x-gpio", |
d88b25be3 gpio: Add TC35892... |
331 |
.driver.owner = THIS_MODULE, |
20406ebff mfd/tc3589x: rena... |
332 333 |
.probe = tc3589x_gpio_probe, .remove = __devexit_p(tc3589x_gpio_remove), |
d88b25be3 gpio: Add TC35892... |
334 |
}; |
20406ebff mfd/tc3589x: rena... |
335 |
static int __init tc3589x_gpio_init(void) |
d88b25be3 gpio: Add TC35892... |
336 |
{ |
20406ebff mfd/tc3589x: rena... |
337 |
return platform_driver_register(&tc3589x_gpio_driver); |
d88b25be3 gpio: Add TC35892... |
338 |
} |
20406ebff mfd/tc3589x: rena... |
339 |
subsys_initcall(tc3589x_gpio_init); |
d88b25be3 gpio: Add TC35892... |
340 |
|
20406ebff mfd/tc3589x: rena... |
341 |
static void __exit tc3589x_gpio_exit(void) |
d88b25be3 gpio: Add TC35892... |
342 |
{ |
20406ebff mfd/tc3589x: rena... |
343 |
platform_driver_unregister(&tc3589x_gpio_driver); |
d88b25be3 gpio: Add TC35892... |
344 |
} |
20406ebff mfd/tc3589x: rena... |
345 |
module_exit(tc3589x_gpio_exit); |
d88b25be3 gpio: Add TC35892... |
346 347 |
MODULE_LICENSE("GPL v2"); |
20406ebff mfd/tc3589x: rena... |
348 |
MODULE_DESCRIPTION("TC3589x GPIO driver"); |
d88b25be3 gpio: Add TC35892... |
349 |
MODULE_AUTHOR("Hanumath Prasad, Rabin Vincent"); |