tc3589x.c (f4e8afdc7ab1b5a0962be02a9dd15d29a81f4c53) | tc3589x.c (20406ebff4a298e6e3abbc1717a90bb3e55dc820) |
---|---|
1/* 2 * Copyright (C) ST-Ericsson SA 2010 3 * 4 * License Terms: GNU General Public License, version 2 5 * Author: Hanumath Prasad <hanumath.prasad@stericsson.com> for ST-Ericsson 6 * Author: Rabin Vincent <rabin.vincent@stericsson.com> for ST-Ericsson 7 */ 8 9#include <linux/module.h> 10#include <linux/interrupt.h> 11#include <linux/irq.h> 12#include <linux/slab.h> 13#include <linux/i2c.h> 14#include <linux/mfd/core.h> 15#include <linux/mfd/tc3589x.h> 16 17/** | 1/* 2 * Copyright (C) ST-Ericsson SA 2010 3 * 4 * License Terms: GNU General Public License, version 2 5 * Author: Hanumath Prasad <hanumath.prasad@stericsson.com> for ST-Ericsson 6 * Author: Rabin Vincent <rabin.vincent@stericsson.com> for ST-Ericsson 7 */ 8 9#include <linux/module.h> 10#include <linux/interrupt.h> 11#include <linux/irq.h> 12#include <linux/slab.h> 13#include <linux/i2c.h> 14#include <linux/mfd/core.h> 15#include <linux/mfd/tc3589x.h> 16 17/** |
18 * tc35892_reg_read() - read a single TC35892 register 19 * @tc35892: Device to read from | 18 * tc3589x_reg_read() - read a single TC3589x register 19 * @tc3589x: Device to read from |
20 * @reg: Register to read 21 */ | 20 * @reg: Register to read 21 */ |
22int tc35892_reg_read(struct tc35892 *tc35892, u8 reg) | 22int tc3589x_reg_read(struct tc3589x *tc3589x, u8 reg) |
23{ 24 int ret; 25 | 23{ 24 int ret; 25 |
26 ret = i2c_smbus_read_byte_data(tc35892->i2c, reg); | 26 ret = i2c_smbus_read_byte_data(tc3589x->i2c, reg); |
27 if (ret < 0) | 27 if (ret < 0) |
28 dev_err(tc35892->dev, "failed to read reg %#x: %d\n", | 28 dev_err(tc3589x->dev, "failed to read reg %#x: %d\n", |
29 reg, ret); 30 31 return ret; 32} | 29 reg, ret); 30 31 return ret; 32} |
33EXPORT_SYMBOL_GPL(tc35892_reg_read); | 33EXPORT_SYMBOL_GPL(tc3589x_reg_read); |
34 35/** | 34 35/** |
36 * tc35892_reg_read() - write a single TC35892 register 37 * @tc35892: Device to write to | 36 * tc3589x_reg_read() - write a single TC3589x register 37 * @tc3589x: Device to write to |
38 * @reg: Register to read 39 * @data: Value to write 40 */ | 38 * @reg: Register to read 39 * @data: Value to write 40 */ |
41int tc35892_reg_write(struct tc35892 *tc35892, u8 reg, u8 data) | 41int tc3589x_reg_write(struct tc3589x *tc3589x, u8 reg, u8 data) |
42{ 43 int ret; 44 | 42{ 43 int ret; 44 |
45 ret = i2c_smbus_write_byte_data(tc35892->i2c, reg, data); | 45 ret = i2c_smbus_write_byte_data(tc3589x->i2c, reg, data); |
46 if (ret < 0) | 46 if (ret < 0) |
47 dev_err(tc35892->dev, "failed to write reg %#x: %d\n", | 47 dev_err(tc3589x->dev, "failed to write reg %#x: %d\n", |
48 reg, ret); 49 50 return ret; 51} | 48 reg, ret); 49 50 return ret; 51} |
52EXPORT_SYMBOL_GPL(tc35892_reg_write); | 52EXPORT_SYMBOL_GPL(tc3589x_reg_write); |
53 54/** | 53 54/** |
55 * tc35892_block_read() - read multiple TC35892 registers 56 * @tc35892: Device to read from | 55 * tc3589x_block_read() - read multiple TC3589x registers 56 * @tc3589x: Device to read from |
57 * @reg: First register 58 * @length: Number of registers 59 * @values: Buffer to write to 60 */ | 57 * @reg: First register 58 * @length: Number of registers 59 * @values: Buffer to write to 60 */ |
61int tc35892_block_read(struct tc35892 *tc35892, u8 reg, u8 length, u8 *values) | 61int tc3589x_block_read(struct tc3589x *tc3589x, u8 reg, u8 length, u8 *values) |
62{ 63 int ret; 64 | 62{ 63 int ret; 64 |
65 ret = i2c_smbus_read_i2c_block_data(tc35892->i2c, reg, length, values); | 65 ret = i2c_smbus_read_i2c_block_data(tc3589x->i2c, reg, length, values); |
66 if (ret < 0) | 66 if (ret < 0) |
67 dev_err(tc35892->dev, "failed to read regs %#x: %d\n", | 67 dev_err(tc3589x->dev, "failed to read regs %#x: %d\n", |
68 reg, ret); 69 70 return ret; 71} | 68 reg, ret); 69 70 return ret; 71} |
72EXPORT_SYMBOL_GPL(tc35892_block_read); | 72EXPORT_SYMBOL_GPL(tc3589x_block_read); |
73 74/** | 73 74/** |
75 * tc35892_block_write() - write multiple TC35892 registers 76 * @tc35892: Device to write to | 75 * tc3589x_block_write() - write multiple TC3589x registers 76 * @tc3589x: Device to write to |
77 * @reg: First register 78 * @length: Number of registers 79 * @values: Values to write 80 */ | 77 * @reg: First register 78 * @length: Number of registers 79 * @values: Values to write 80 */ |
81int tc35892_block_write(struct tc35892 *tc35892, u8 reg, u8 length, | 81int tc3589x_block_write(struct tc3589x *tc3589x, u8 reg, u8 length, |
82 const u8 *values) 83{ 84 int ret; 85 | 82 const u8 *values) 83{ 84 int ret; 85 |
86 ret = i2c_smbus_write_i2c_block_data(tc35892->i2c, reg, length, | 86 ret = i2c_smbus_write_i2c_block_data(tc3589x->i2c, reg, length, |
87 values); 88 if (ret < 0) | 87 values); 88 if (ret < 0) |
89 dev_err(tc35892->dev, "failed to write regs %#x: %d\n", | 89 dev_err(tc3589x->dev, "failed to write regs %#x: %d\n", |
90 reg, ret); 91 92 return ret; 93} | 90 reg, ret); 91 92 return ret; 93} |
94EXPORT_SYMBOL_GPL(tc35892_block_write); | 94EXPORT_SYMBOL_GPL(tc3589x_block_write); |
95 96/** | 95 96/** |
97 * tc35892_set_bits() - set the value of a bitfield in a TC35892 register 98 * @tc35892: Device to write to | 97 * tc3589x_set_bits() - set the value of a bitfield in a TC3589x register 98 * @tc3589x: Device to write to |
99 * @reg: Register to write 100 * @mask: Mask of bits to set 101 * @values: Value to set 102 */ | 99 * @reg: Register to write 100 * @mask: Mask of bits to set 101 * @values: Value to set 102 */ |
103int tc35892_set_bits(struct tc35892 *tc35892, u8 reg, u8 mask, u8 val) | 103int tc3589x_set_bits(struct tc3589x *tc3589x, u8 reg, u8 mask, u8 val) |
104{ 105 int ret; 106 | 104{ 105 int ret; 106 |
107 mutex_lock(&tc35892->lock); | 107 mutex_lock(&tc3589x->lock); |
108 | 108 |
109 ret = tc35892_reg_read(tc35892, reg); | 109 ret = tc3589x_reg_read(tc3589x, reg); |
110 if (ret < 0) 111 goto out; 112 113 ret &= ~mask; 114 ret |= val; 115 | 110 if (ret < 0) 111 goto out; 112 113 ret &= ~mask; 114 ret |= val; 115 |
116 ret = tc35892_reg_write(tc35892, reg, ret); | 116 ret = tc3589x_reg_write(tc3589x, reg, ret); |
117 118out: | 117 118out: |
119 mutex_unlock(&tc35892->lock); | 119 mutex_unlock(&tc3589x->lock); |
120 return ret; 121} | 120 return ret; 121} |
122EXPORT_SYMBOL_GPL(tc35892_set_bits); | 122EXPORT_SYMBOL_GPL(tc3589x_set_bits); |
123 124static struct resource gpio_resources[] = { 125 { | 123 124static struct resource gpio_resources[] = { 125 { |
126 .start = TC35892_INT_GPIIRQ, 127 .end = TC35892_INT_GPIIRQ, | 126 .start = TC3589x_INT_GPIIRQ, 127 .end = TC3589x_INT_GPIIRQ, |
128 .flags = IORESOURCE_IRQ, 129 }, 130}; 131 | 128 .flags = IORESOURCE_IRQ, 129 }, 130}; 131 |
132static struct mfd_cell tc35892_devs[] = { | 132static struct mfd_cell tc3589x_devs[] = { |
133 { | 133 { |
134 .name = "tc35892-gpio", | 134 .name = "tc3589x-gpio", |
135 .num_resources = ARRAY_SIZE(gpio_resources), 136 .resources = &gpio_resources[0], 137 }, 138}; 139 | 135 .num_resources = ARRAY_SIZE(gpio_resources), 136 .resources = &gpio_resources[0], 137 }, 138}; 139 |
140static irqreturn_t tc35892_irq(int irq, void *data) | 140static irqreturn_t tc3589x_irq(int irq, void *data) |
141{ | 141{ |
142 struct tc35892 *tc35892 = data; | 142 struct tc3589x *tc3589x = data; |
143 int status; 144 | 143 int status; 144 |
145 status = tc35892_reg_read(tc35892, TC35892_IRQST); | 145 status = tc3589x_reg_read(tc3589x, TC3589x_IRQST); |
146 if (status < 0) 147 return IRQ_NONE; 148 149 while (status) { 150 int bit = __ffs(status); 151 | 146 if (status < 0) 147 return IRQ_NONE; 148 149 while (status) { 150 int bit = __ffs(status); 151 |
152 handle_nested_irq(tc35892->irq_base + bit); | 152 handle_nested_irq(tc3589x->irq_base + bit); |
153 status &= ~(1 << bit); 154 } 155 156 /* 157 * A dummy read or write (to any register) appears to be necessary to 158 * have the last interrupt clear (for example, GPIO IC write) take 159 * effect. 160 */ | 153 status &= ~(1 << bit); 154 } 155 156 /* 157 * A dummy read or write (to any register) appears to be necessary to 158 * have the last interrupt clear (for example, GPIO IC write) take 159 * effect. 160 */ |
161 tc35892_reg_read(tc35892, TC35892_IRQST); | 161 tc3589x_reg_read(tc3589x, TC3589x_IRQST); |
162 163 return IRQ_HANDLED; 164} 165 | 162 163 return IRQ_HANDLED; 164} 165 |
166static void tc35892_irq_dummy(unsigned int irq) | 166static void tc3589x_irq_dummy(unsigned int irq) |
167{ 168 /* No mask/unmask at this level */ 169} 170 | 167{ 168 /* No mask/unmask at this level */ 169} 170 |
171static struct irq_chip tc35892_irq_chip = { 172 .name = "tc35892", 173 .mask = tc35892_irq_dummy, 174 .unmask = tc35892_irq_dummy, | 171static struct irq_chip tc3589x_irq_chip = { 172 .name = "tc3589x", 173 .mask = tc3589x_irq_dummy, 174 .unmask = tc3589x_irq_dummy, |
175}; 176 | 175}; 176 |
177static int tc35892_irq_init(struct tc35892 *tc35892) | 177static int tc3589x_irq_init(struct tc3589x *tc3589x) |
178{ | 178{ |
179 int base = tc35892->irq_base; | 179 int base = tc3589x->irq_base; |
180 int irq; 181 | 180 int irq; 181 |
182 for (irq = base; irq < base + TC35892_NR_INTERNAL_IRQS; irq++) { 183 set_irq_chip_data(irq, tc35892); 184 set_irq_chip_and_handler(irq, &tc35892_irq_chip, | 182 for (irq = base; irq < base + TC3589x_NR_INTERNAL_IRQS; irq++) { 183 set_irq_chip_data(irq, tc3589x); 184 set_irq_chip_and_handler(irq, &tc3589x_irq_chip, |
185 handle_edge_irq); 186 set_irq_nested_thread(irq, 1); 187#ifdef CONFIG_ARM 188 set_irq_flags(irq, IRQF_VALID); 189#else 190 set_irq_noprobe(irq); 191#endif 192 } 193 194 return 0; 195} 196 | 185 handle_edge_irq); 186 set_irq_nested_thread(irq, 1); 187#ifdef CONFIG_ARM 188 set_irq_flags(irq, IRQF_VALID); 189#else 190 set_irq_noprobe(irq); 191#endif 192 } 193 194 return 0; 195} 196 |
197static void tc35892_irq_remove(struct tc35892 *tc35892) | 197static void tc3589x_irq_remove(struct tc3589x *tc3589x) |
198{ | 198{ |
199 int base = tc35892->irq_base; | 199 int base = tc3589x->irq_base; |
200 int irq; 201 | 200 int irq; 201 |
202 for (irq = base; irq < base + TC35892_NR_INTERNAL_IRQS; irq++) { | 202 for (irq = base; irq < base + TC3589x_NR_INTERNAL_IRQS; irq++) { |
203#ifdef CONFIG_ARM 204 set_irq_flags(irq, 0); 205#endif 206 set_irq_chip_and_handler(irq, NULL, NULL); 207 set_irq_chip_data(irq, NULL); 208 } 209} 210 | 203#ifdef CONFIG_ARM 204 set_irq_flags(irq, 0); 205#endif 206 set_irq_chip_and_handler(irq, NULL, NULL); 207 set_irq_chip_data(irq, NULL); 208 } 209} 210 |
211static int tc35892_chip_init(struct tc35892 *tc35892) | 211static int tc3589x_chip_init(struct tc3589x *tc3589x) |
212{ 213 int manf, ver, ret; 214 | 212{ 213 int manf, ver, ret; 214 |
215 manf = tc35892_reg_read(tc35892, TC35892_MANFCODE); | 215 manf = tc3589x_reg_read(tc3589x, TC3589x_MANFCODE); |
216 if (manf < 0) 217 return manf; 218 | 216 if (manf < 0) 217 return manf; 218 |
219 ver = tc35892_reg_read(tc35892, TC35892_VERSION); | 219 ver = tc3589x_reg_read(tc3589x, TC3589x_VERSION); |
220 if (ver < 0) 221 return ver; 222 | 220 if (ver < 0) 221 return ver; 222 |
223 if (manf != TC35892_MANFCODE_MAGIC) { 224 dev_err(tc35892->dev, "unknown manufacturer: %#x\n", manf); | 223 if (manf != TC3589x_MANFCODE_MAGIC) { 224 dev_err(tc3589x->dev, "unknown manufacturer: %#x\n", manf); |
225 return -EINVAL; 226 } 227 | 225 return -EINVAL; 226 } 227 |
228 dev_info(tc35892->dev, "manufacturer: %#x, version: %#x\n", manf, ver); | 228 dev_info(tc3589x->dev, "manufacturer: %#x, version: %#x\n", manf, ver); |
229 230 /* Put everything except the IRQ module into reset */ | 229 230 /* Put everything except the IRQ module into reset */ |
231 ret = tc35892_reg_write(tc35892, TC35892_RSTCTRL, 232 TC35892_RSTCTRL_TIMRST 233 | TC35892_RSTCTRL_ROTRST 234 | TC35892_RSTCTRL_KBDRST 235 | TC35892_RSTCTRL_GPIRST); | 231 ret = tc3589x_reg_write(tc3589x, TC3589x_RSTCTRL, 232 TC3589x_RSTCTRL_TIMRST 233 | TC3589x_RSTCTRL_ROTRST 234 | TC3589x_RSTCTRL_KBDRST 235 | TC3589x_RSTCTRL_GPIRST); |
236 if (ret < 0) 237 return ret; 238 239 /* Clear the reset interrupt. */ | 236 if (ret < 0) 237 return ret; 238 239 /* Clear the reset interrupt. */ |
240 return tc35892_reg_write(tc35892, TC35892_RSTINTCLR, 0x1); | 240 return tc3589x_reg_write(tc3589x, TC3589x_RSTINTCLR, 0x1); |
241} 242 | 241} 242 |
243static int __devinit tc35892_probe(struct i2c_client *i2c, | 243static int __devinit tc3589x_probe(struct i2c_client *i2c, |
244 const struct i2c_device_id *id) 245{ | 244 const struct i2c_device_id *id) 245{ |
246 struct tc35892_platform_data *pdata = i2c->dev.platform_data; 247 struct tc35892 *tc35892; | 246 struct tc3589x_platform_data *pdata = i2c->dev.platform_data; 247 struct tc3589x *tc3589x; |
248 int ret; 249 250 if (!i2c_check_functionality(i2c->adapter, I2C_FUNC_SMBUS_BYTE_DATA 251 | I2C_FUNC_SMBUS_I2C_BLOCK)) 252 return -EIO; 253 | 248 int ret; 249 250 if (!i2c_check_functionality(i2c->adapter, I2C_FUNC_SMBUS_BYTE_DATA 251 | I2C_FUNC_SMBUS_I2C_BLOCK)) 252 return -EIO; 253 |
254 tc35892 = kzalloc(sizeof(struct tc35892), GFP_KERNEL); 255 if (!tc35892) | 254 tc3589x = kzalloc(sizeof(struct tc3589x), GFP_KERNEL); 255 if (!tc3589x) |
256 return -ENOMEM; 257 | 256 return -ENOMEM; 257 |
258 mutex_init(&tc35892->lock); | 258 mutex_init(&tc3589x->lock); |
259 | 259 |
260 tc35892->dev = &i2c->dev; 261 tc35892->i2c = i2c; 262 tc35892->pdata = pdata; 263 tc35892->irq_base = pdata->irq_base; 264 tc35892->num_gpio = id->driver_data; | 260 tc3589x->dev = &i2c->dev; 261 tc3589x->i2c = i2c; 262 tc3589x->pdata = pdata; 263 tc3589x->irq_base = pdata->irq_base; 264 tc3589x->num_gpio = id->driver_data; |
265 | 265 |
266 i2c_set_clientdata(i2c, tc35892); | 266 i2c_set_clientdata(i2c, tc3589x); |
267 | 267 |
268 ret = tc35892_chip_init(tc35892); | 268 ret = tc3589x_chip_init(tc3589x); |
269 if (ret) 270 goto out_free; 271 | 269 if (ret) 270 goto out_free; 271 |
272 ret = tc35892_irq_init(tc35892); | 272 ret = tc3589x_irq_init(tc3589x); |
273 if (ret) 274 goto out_free; 275 | 273 if (ret) 274 goto out_free; 275 |
276 ret = request_threaded_irq(tc35892->i2c->irq, NULL, tc35892_irq, | 276 ret = request_threaded_irq(tc3589x->i2c->irq, NULL, tc3589x_irq, |
277 IRQF_TRIGGER_FALLING | IRQF_ONESHOT, | 277 IRQF_TRIGGER_FALLING | IRQF_ONESHOT, |
278 "tc35892", tc35892); | 278 "tc3589x", tc3589x); |
279 if (ret) { | 279 if (ret) { |
280 dev_err(tc35892->dev, "failed to request IRQ: %d\n", ret); | 280 dev_err(tc3589x->dev, "failed to request IRQ: %d\n", ret); |
281 goto out_removeirq; 282 } 283 | 281 goto out_removeirq; 282 } 283 |
284 ret = mfd_add_devices(tc35892->dev, -1, tc35892_devs, 285 ARRAY_SIZE(tc35892_devs), NULL, 286 tc35892->irq_base); | 284 ret = mfd_add_devices(tc3589x->dev, -1, tc3589x_devs, 285 ARRAY_SIZE(tc3589x_devs), NULL, 286 tc3589x->irq_base); |
287 if (ret) { | 287 if (ret) { |
288 dev_err(tc35892->dev, "failed to add children\n"); | 288 dev_err(tc3589x->dev, "failed to add children\n"); |
289 goto out_freeirq; 290 } 291 292 return 0; 293 294out_freeirq: | 289 goto out_freeirq; 290 } 291 292 return 0; 293 294out_freeirq: |
295 free_irq(tc35892->i2c->irq, tc35892); | 295 free_irq(tc3589x->i2c->irq, tc3589x); |
296out_removeirq: | 296out_removeirq: |
297 tc35892_irq_remove(tc35892); | 297 tc3589x_irq_remove(tc3589x); |
298out_free: | 298out_free: |
299 kfree(tc35892); | 299 kfree(tc3589x); |
300 return ret; 301} 302 | 300 return ret; 301} 302 |
303static int __devexit tc35892_remove(struct i2c_client *client) | 303static int __devexit tc3589x_remove(struct i2c_client *client) |
304{ | 304{ |
305 struct tc35892 *tc35892 = i2c_get_clientdata(client); | 305 struct tc3589x *tc3589x = i2c_get_clientdata(client); |
306 | 306 |
307 mfd_remove_devices(tc35892->dev); | 307 mfd_remove_devices(tc3589x->dev); |
308 | 308 |
309 free_irq(tc35892->i2c->irq, tc35892); 310 tc35892_irq_remove(tc35892); | 309 free_irq(tc3589x->i2c->irq, tc3589x); 310 tc3589x_irq_remove(tc3589x); |
311 | 311 |
312 kfree(tc35892); | 312 kfree(tc3589x); |
313 314 return 0; 315} 316 | 313 314 return 0; 315} 316 |
317static const struct i2c_device_id tc35892_id[] = { 318 { "tc35892", 24 }, | 317static const struct i2c_device_id tc3589x_id[] = { 318 { "tc3589x", 24 }, |
319 { } 320}; | 319 { } 320}; |
321MODULE_DEVICE_TABLE(i2c, tc35892_id); | 321MODULE_DEVICE_TABLE(i2c, tc3589x_id); |
322 | 322 |
323static struct i2c_driver tc35892_driver = { 324 .driver.name = "tc35892", | 323static struct i2c_driver tc3589x_driver = { 324 .driver.name = "tc3589x", |
325 .driver.owner = THIS_MODULE, | 325 .driver.owner = THIS_MODULE, |
326 .probe = tc35892_probe, 327 .remove = __devexit_p(tc35892_remove), 328 .id_table = tc35892_id, | 326 .probe = tc3589x_probe, 327 .remove = __devexit_p(tc3589x_remove), 328 .id_table = tc3589x_id, |
329}; 330 | 329}; 330 |
331static int __init tc35892_init(void) | 331static int __init tc3589x_init(void) |
332{ | 332{ |
333 return i2c_add_driver(&tc35892_driver); | 333 return i2c_add_driver(&tc3589x_driver); |
334} | 334} |
335subsys_initcall(tc35892_init); | 335subsys_initcall(tc3589x_init); |
336 | 336 |
337static void __exit tc35892_exit(void) | 337static void __exit tc3589x_exit(void) |
338{ | 338{ |
339 i2c_del_driver(&tc35892_driver); | 339 i2c_del_driver(&tc3589x_driver); |
340} | 340} |
341module_exit(tc35892_exit); | 341module_exit(tc3589x_exit); |
342 343MODULE_LICENSE("GPL v2"); | 342 343MODULE_LICENSE("GPL v2"); |
344MODULE_DESCRIPTION("TC35892 MFD core driver"); | 344MODULE_DESCRIPTION("TC3589x MFD core driver"); |
345MODULE_AUTHOR("Hanumath Prasad, Rabin Vincent"); | 345MODULE_AUTHOR("Hanumath Prasad, Rabin Vincent"); |