diff options
Diffstat (limited to 'drivers/mfd/ab3100-core.c')
-rw-r--r-- | drivers/mfd/ab3100-core.c | 99 |
1 files changed, 69 insertions, 30 deletions
diff --git a/drivers/mfd/ab3100-core.c b/drivers/mfd/ab3100-core.c index e4ca5909e424..53ebfee548fa 100644 --- a/drivers/mfd/ab3100-core.c +++ b/drivers/mfd/ab3100-core.c | |||
@@ -19,7 +19,7 @@ | |||
19 | #include <linux/debugfs.h> | 19 | #include <linux/debugfs.h> |
20 | #include <linux/seq_file.h> | 20 | #include <linux/seq_file.h> |
21 | #include <linux/uaccess.h> | 21 | #include <linux/uaccess.h> |
22 | #include <linux/mfd/ab3100.h> | 22 | #include <linux/mfd/abx500.h> |
23 | 23 | ||
24 | /* These are the only registers inside AB3100 used in this main file */ | 24 | /* These are the only registers inside AB3100 used in this main file */ |
25 | 25 | ||
@@ -59,24 +59,15 @@ | |||
59 | * The AB3100 is usually assigned address 0x48 (7-bit) | 59 | * The AB3100 is usually assigned address 0x48 (7-bit) |
60 | * The chip is defined in the platform i2c_board_data section. | 60 | * The chip is defined in the platform i2c_board_data section. |
61 | */ | 61 | */ |
62 | 62 | static int ab3100_get_chip_id(struct device *dev) | |
63 | u8 ab3100_get_chip_type(struct ab3100 *ab3100) | ||
64 | { | 63 | { |
65 | u8 chip = ABUNKNOWN; | 64 | struct ab3100 *ab3100 = dev_get_drvdata(dev->parent); |
66 | 65 | ||
67 | switch (ab3100->chip_id & 0xf0) { | 66 | return (int)ab3100->chip_id; |
68 | case 0xa0: | ||
69 | chip = AB3000; | ||
70 | break; | ||
71 | case 0xc0: | ||
72 | chip = AB3100; | ||
73 | break; | ||
74 | } | ||
75 | return chip; | ||
76 | } | 67 | } |
77 | EXPORT_SYMBOL(ab3100_get_chip_type); | ||
78 | 68 | ||
79 | int ab3100_set_register_interruptible(struct ab3100 *ab3100, u8 reg, u8 regval) | 69 | static int ab3100_set_register_interruptible(struct ab3100 *ab3100, |
70 | u8 reg, u8 regval) | ||
80 | { | 71 | { |
81 | u8 regandval[2] = {reg, regval}; | 72 | u8 regandval[2] = {reg, regval}; |
82 | int err; | 73 | int err; |
@@ -108,8 +99,14 @@ int ab3100_set_register_interruptible(struct ab3100 *ab3100, u8 reg, u8 regval) | |||
108 | mutex_unlock(&ab3100->access_mutex); | 99 | mutex_unlock(&ab3100->access_mutex); |
109 | return err; | 100 | return err; |
110 | } | 101 | } |
111 | EXPORT_SYMBOL(ab3100_set_register_interruptible); | ||
112 | 102 | ||
103 | static int set_register_interruptible(struct device *dev, | ||
104 | u8 bank, u8 reg, u8 value) | ||
105 | { | ||
106 | struct ab3100 *ab3100 = dev_get_drvdata(dev->parent); | ||
107 | |||
108 | return ab3100_set_register_interruptible(ab3100, reg, value); | ||
109 | } | ||
113 | 110 | ||
114 | /* | 111 | /* |
115 | * The test registers exist at an I2C bus address up one | 112 | * The test registers exist at an I2C bus address up one |
@@ -148,8 +145,8 @@ static int ab3100_set_test_register_interruptible(struct ab3100 *ab3100, | |||
148 | return err; | 145 | return err; |
149 | } | 146 | } |
150 | 147 | ||
151 | 148 | static int ab3100_get_register_interruptible(struct ab3100 *ab3100, | |
152 | int ab3100_get_register_interruptible(struct ab3100 *ab3100, u8 reg, u8 *regval) | 149 | u8 reg, u8 *regval) |
153 | { | 150 | { |
154 | int err; | 151 | int err; |
155 | 152 | ||
@@ -203,10 +200,16 @@ int ab3100_get_register_interruptible(struct ab3100 *ab3100, u8 reg, u8 *regval) | |||
203 | mutex_unlock(&ab3100->access_mutex); | 200 | mutex_unlock(&ab3100->access_mutex); |
204 | return err; | 201 | return err; |
205 | } | 202 | } |
206 | EXPORT_SYMBOL(ab3100_get_register_interruptible); | ||
207 | 203 | ||
204 | static int get_register_interruptible(struct device *dev, u8 bank, u8 reg, | ||
205 | u8 *value) | ||
206 | { | ||
207 | struct ab3100 *ab3100 = dev_get_drvdata(dev->parent); | ||
208 | |||
209 | return ab3100_get_register_interruptible(ab3100, reg, value); | ||
210 | } | ||
208 | 211 | ||
209 | int ab3100_get_register_page_interruptible(struct ab3100 *ab3100, | 212 | static int ab3100_get_register_page_interruptible(struct ab3100 *ab3100, |
210 | u8 first_reg, u8 *regvals, u8 numregs) | 213 | u8 first_reg, u8 *regvals, u8 numregs) |
211 | { | 214 | { |
212 | int err; | 215 | int err; |
@@ -260,10 +263,17 @@ int ab3100_get_register_page_interruptible(struct ab3100 *ab3100, | |||
260 | mutex_unlock(&ab3100->access_mutex); | 263 | mutex_unlock(&ab3100->access_mutex); |
261 | return err; | 264 | return err; |
262 | } | 265 | } |
263 | EXPORT_SYMBOL(ab3100_get_register_page_interruptible); | ||
264 | 266 | ||
267 | static int get_register_page_interruptible(struct device *dev, u8 bank, | ||
268 | u8 first_reg, u8 *regvals, u8 numregs) | ||
269 | { | ||
270 | struct ab3100 *ab3100 = dev_get_drvdata(dev->parent); | ||
271 | |||
272 | return ab3100_get_register_page_interruptible(ab3100, | ||
273 | first_reg, regvals, numregs); | ||
274 | } | ||
265 | 275 | ||
266 | int ab3100_mask_and_set_register_interruptible(struct ab3100 *ab3100, | 276 | static int ab3100_mask_and_set_register_interruptible(struct ab3100 *ab3100, |
267 | u8 reg, u8 andmask, u8 ormask) | 277 | u8 reg, u8 andmask, u8 ormask) |
268 | { | 278 | { |
269 | u8 regandval[2] = {reg, 0}; | 279 | u8 regandval[2] = {reg, 0}; |
@@ -331,8 +341,15 @@ int ab3100_mask_and_set_register_interruptible(struct ab3100 *ab3100, | |||
331 | mutex_unlock(&ab3100->access_mutex); | 341 | mutex_unlock(&ab3100->access_mutex); |
332 | return err; | 342 | return err; |
333 | } | 343 | } |
334 | EXPORT_SYMBOL(ab3100_mask_and_set_register_interruptible); | ||
335 | 344 | ||
345 | static int mask_and_set_register_interruptible(struct device *dev, u8 bank, | ||
346 | u8 reg, u8 bitmask, u8 bitvalues) | ||
347 | { | ||
348 | struct ab3100 *ab3100 = dev_get_drvdata(dev->parent); | ||
349 | |||
350 | return ab3100_mask_and_set_register_interruptible(ab3100, | ||
351 | reg, bitmask, (bitmask & bitvalues)); | ||
352 | } | ||
336 | 353 | ||
337 | /* | 354 | /* |
338 | * Register a simple callback for handling any AB3100 events. | 355 | * Register a simple callback for handling any AB3100 events. |
@@ -357,15 +374,27 @@ int ab3100_event_unregister(struct ab3100 *ab3100, | |||
357 | EXPORT_SYMBOL(ab3100_event_unregister); | 374 | EXPORT_SYMBOL(ab3100_event_unregister); |
358 | 375 | ||
359 | 376 | ||
360 | int ab3100_event_registers_startup_state_get(struct ab3100 *ab3100, | 377 | static int ab3100_event_registers_startup_state_get(struct device *dev, |
361 | u32 *fatevent) | 378 | u8 *event) |
362 | { | 379 | { |
380 | struct ab3100 *ab3100 = dev_get_drvdata(dev->parent); | ||
363 | if (!ab3100->startup_events_read) | 381 | if (!ab3100->startup_events_read) |
364 | return -EAGAIN; /* Try again later */ | 382 | return -EAGAIN; /* Try again later */ |
365 | *fatevent = ab3100->startup_events; | 383 | memcpy(event, ab3100->startup_events, 3); |
366 | return 0; | 384 | return 0; |
367 | } | 385 | } |
368 | EXPORT_SYMBOL(ab3100_event_registers_startup_state_get); | 386 | |
387 | static struct abx500_ops ab3100_ops = { | ||
388 | .get_chip_id = ab3100_get_chip_id, | ||
389 | .set_register = set_register_interruptible, | ||
390 | .get_register = get_register_interruptible, | ||
391 | .get_register_page = get_register_page_interruptible, | ||
392 | .set_register_page = NULL, | ||
393 | .mask_and_set_register = mask_and_set_register_interruptible, | ||
394 | .event_registers_startup_state_get = | ||
395 | ab3100_event_registers_startup_state_get, | ||
396 | .startup_irq_enabled = NULL, | ||
397 | }; | ||
369 | 398 | ||
370 | /* | 399 | /* |
371 | * This is a threaded interrupt handler so we can make some | 400 | * This is a threaded interrupt handler so we can make some |
@@ -390,7 +419,9 @@ static irqreturn_t ab3100_irq_handler(int irq, void *data) | |||
390 | event_regs[2]; | 419 | event_regs[2]; |
391 | 420 | ||
392 | if (!ab3100->startup_events_read) { | 421 | if (!ab3100->startup_events_read) { |
393 | ab3100->startup_events = fatevent; | 422 | ab3100->startup_events[0] = event_regs[0]; |
423 | ab3100->startup_events[1] = event_regs[1]; | ||
424 | ab3100->startup_events[2] = event_regs[2]; | ||
394 | ab3100->startup_events_read = true; | 425 | ab3100->startup_events_read = true; |
395 | } | 426 | } |
396 | /* | 427 | /* |
@@ -703,7 +734,8 @@ static int __init ab3100_setup(struct ab3100 *ab3100) | |||
703 | dev_warn(ab3100->dev, | 734 | dev_warn(ab3100->dev, |
704 | "AB3100 P1E variant detected, " | 735 | "AB3100 P1E variant detected, " |
705 | "forcing chip to 32KHz\n"); | 736 | "forcing chip to 32KHz\n"); |
706 | err = ab3100_set_test_register_interruptible(ab3100, 0x02, 0x08); | 737 | err = ab3100_set_test_register_interruptible(ab3100, |
738 | 0x02, 0x08); | ||
707 | } | 739 | } |
708 | 740 | ||
709 | exit_no_setup: | 741 | exit_no_setup: |
@@ -898,6 +930,10 @@ static int __init ab3100_probe(struct i2c_client *client, | |||
898 | if (err) | 930 | if (err) |
899 | goto exit_no_irq; | 931 | goto exit_no_irq; |
900 | 932 | ||
933 | err = abx500_register_ops(&client->dev, &ab3100_ops); | ||
934 | if (err) | ||
935 | goto exit_no_ops; | ||
936 | |||
901 | /* Set parent and a pointer back to the container in device data */ | 937 | /* Set parent and a pointer back to the container in device data */ |
902 | for (i = 0; i < ARRAY_SIZE(ab3100_platform_devs); i++) { | 938 | for (i = 0; i < ARRAY_SIZE(ab3100_platform_devs); i++) { |
903 | ab3100_platform_devs[i]->dev.parent = | 939 | ab3100_platform_devs[i]->dev.parent = |
@@ -915,11 +951,13 @@ static int __init ab3100_probe(struct i2c_client *client, | |||
915 | 951 | ||
916 | return 0; | 952 | return 0; |
917 | 953 | ||
954 | exit_no_ops: | ||
918 | exit_no_irq: | 955 | exit_no_irq: |
919 | exit_no_setup: | 956 | exit_no_setup: |
920 | i2c_unregister_device(ab3100->testreg_client); | 957 | i2c_unregister_device(ab3100->testreg_client); |
921 | exit_no_testreg_client: | 958 | exit_no_testreg_client: |
922 | exit_no_detect: | 959 | exit_no_detect: |
960 | i2c_set_clientdata(client, NULL); | ||
923 | kfree(ab3100); | 961 | kfree(ab3100); |
924 | return err; | 962 | return err; |
925 | } | 963 | } |
@@ -941,6 +979,7 @@ static int __exit ab3100_remove(struct i2c_client *client) | |||
941 | * their notifiers so deactivate IRQ | 979 | * their notifiers so deactivate IRQ |
942 | */ | 980 | */ |
943 | free_irq(client->irq, ab3100); | 981 | free_irq(client->irq, ab3100); |
982 | i2c_set_clientdata(client, NULL); | ||
944 | kfree(ab3100); | 983 | kfree(ab3100); |
945 | return 0; | 984 | return 0; |
946 | } | 985 | } |