aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mfd/twl-core.c
diff options
context:
space:
mode:
authorBalaji T K <balajitk@ti.com>2009-12-13 18:25:31 -0500
committerSamuel Ortiz <sameo@linux.intel.com>2009-12-13 18:25:31 -0500
commite8deb28ca8e221de0239eafb3c3d431d8854278e (patch)
tree2dffdb207366aa0a8f229775515fc207c16f8574 /drivers/mfd/twl-core.c
parentc4aa6f314328142974c78377cd9476f8ec6f0eba (diff)
mfd: Add support for twl6030 irq framework
This patch adds support for phoenix interrupt framework. New iInterrupt status register A, B, C are introduced in Phoenix and are cleared on write. Due to the differences in interrupt handling with respect to TWL4030, twl6030-irq.c is created for TWL6030 PMIC Signed-off-by: Rajendra Nayak <rnayak@ti.com> Signed-off-by: Balaji T K <balajitk@ti.com> Signed-off-by: Santosh Shilimkar <santosh.shilimkar@ti.com> Reviewed-by: Tony Lindgren <tony@atomide.com> Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
Diffstat (limited to 'drivers/mfd/twl-core.c')
-rw-r--r--drivers/mfd/twl-core.c120
1 files changed, 106 insertions, 14 deletions
diff --git a/drivers/mfd/twl-core.c b/drivers/mfd/twl-core.c
index 79946fe800af..c48a6138c575 100644
--- a/drivers/mfd/twl-core.c
+++ b/drivers/mfd/twl-core.c
@@ -181,6 +181,30 @@
181/* Triton Core internal information (END) */ 181/* Triton Core internal information (END) */
182 182
183 183
184/* subchip/slave 0 0x48 - POWER */
185#define TWL6030_BASEADD_RTC 0x0000
186#define TWL6030_BASEADD_MEM 0x0017
187#define TWL6030_BASEADD_PM_MASTER 0x001F
188#define TWL6030_BASEADD_PM_SLAVE_MISC 0x0030 /* PM_RECEIVER */
189#define TWL6030_BASEADD_PM_MISC 0x00E2
190#define TWL6030_BASEADD_PM_PUPD 0x00F0
191
192/* subchip/slave 1 0x49 - FEATURE */
193#define TWL6030_BASEADD_USB 0x0000
194#define TWL6030_BASEADD_GPADC_CTRL 0x002E
195#define TWL6030_BASEADD_AUX 0x0090
196#define TWL6030_BASEADD_PWM 0x00BA
197#define TWL6030_BASEADD_GASGAUGE 0x00C0
198#define TWL6030_BASEADD_PIH 0x00D0
199#define TWL6030_BASEADD_CHARGER 0x00E0
200
201/* subchip/slave 2 0x4A - DFT */
202#define TWL6030_BASEADD_DIEID 0x00C0
203
204/* subchip/slave 3 0x4B - AUDIO */
205#define TWL6030_BASEADD_AUDIO 0x0000
206#define TWL6030_BASEADD_RSV 0x0000
207
184/* Few power values */ 208/* Few power values */
185#define R_CFG_BOOT 0x05 209#define R_CFG_BOOT 0x05
186#define R_PROTECT_KEY 0x0E 210#define R_PROTECT_KEY 0x0E
@@ -202,13 +226,21 @@
202#define TWL4030_VAUX2 BIT(0) /* pre-5030 voltage ranges */ 226#define TWL4030_VAUX2 BIT(0) /* pre-5030 voltage ranges */
203#define TPS_SUBSET BIT(1) /* tps659[23]0 have fewer LDOs */ 227#define TPS_SUBSET BIT(1) /* tps659[23]0 have fewer LDOs */
204#define TWL5031 BIT(2) /* twl5031 has different registers */ 228#define TWL5031 BIT(2) /* twl5031 has different registers */
229#define TWL6030_CLASS BIT(3) /* TWL6030 class */
205 230
206/*----------------------------------------------------------------------*/ 231/*----------------------------------------------------------------------*/
207 232
208/* is driver active, bound to a chip? */ 233/* is driver active, bound to a chip? */
209static bool inuse; 234static bool inuse;
210 235
211/* Structure for each TWL4030 Slave */ 236static unsigned int twl_id;
237unsigned int twl_rev(void)
238{
239 return twl_id;
240}
241EXPORT_SYMBOL(twl_rev);
242
243/* Structure for each TWL4030/TWL6030 Slave */
212struct twl_client { 244struct twl_client {
213 struct i2c_client *client; 245 struct i2c_client *client;
214 u8 address; 246 u8 address;
@@ -228,11 +260,12 @@ struct twl_mapping {
228 unsigned char sid; /* Slave ID */ 260 unsigned char sid; /* Slave ID */
229 unsigned char base; /* base address */ 261 unsigned char base; /* base address */
230}; 262};
263struct twl_mapping *twl_map;
231 264
232static struct twl_mapping twl4030_map[TWL4030_MODULE_LAST + 1] = { 265static struct twl_mapping twl4030_map[TWL4030_MODULE_LAST + 1] = {
233 /* 266 /*
234 * NOTE: don't change this table without updating the 267 * NOTE: don't change this table without updating the
235 * <linux/i2c/twl4030.h> defines for TWL4030_MODULE_* 268 * <linux/i2c/twl.h> defines for TWL4030_MODULE_*
236 * so they continue to match the order in this table. 269 * so they continue to match the order in this table.
237 */ 270 */
238 271
@@ -265,6 +298,40 @@ static struct twl_mapping twl4030_map[TWL4030_MODULE_LAST + 1] = {
265 { 3, TWL4030_BASEADD_SECURED_REG }, 298 { 3, TWL4030_BASEADD_SECURED_REG },
266}; 299};
267 300
301static struct twl_mapping twl6030_map[] = {
302 /*
303 * NOTE: don't change this table without updating the
304 * <linux/i2c/twl.h> defines for TWL4030_MODULE_*
305 * so they continue to match the order in this table.
306 */
307 { SUB_CHIP_ID1, TWL6030_BASEADD_USB },
308 { SUB_CHIP_ID3, TWL6030_BASEADD_AUDIO },
309 { SUB_CHIP_ID2, TWL6030_BASEADD_DIEID },
310 { SUB_CHIP_ID2, TWL6030_BASEADD_RSV },
311 { SUB_CHIP_ID1, TWL6030_BASEADD_PIH },
312
313 { SUB_CHIP_ID2, TWL6030_BASEADD_RSV },
314 { SUB_CHIP_ID2, TWL6030_BASEADD_RSV },
315 { SUB_CHIP_ID1, TWL6030_BASEADD_GPADC_CTRL },
316 { SUB_CHIP_ID2, TWL6030_BASEADD_RSV },
317 { SUB_CHIP_ID2, TWL6030_BASEADD_RSV },
318
319 { SUB_CHIP_ID1, TWL6030_BASEADD_CHARGER },
320 { SUB_CHIP_ID1, TWL6030_BASEADD_GASGAUGE },
321 { SUB_CHIP_ID1, TWL6030_BASEADD_PWM },
322 { SUB_CHIP_ID2, TWL6030_BASEADD_RSV },
323 { SUB_CHIP_ID2, TWL6030_BASEADD_RSV },
324
325 { SUB_CHIP_ID2, TWL6030_BASEADD_RSV },
326 { SUB_CHIP_ID2, TWL6030_BASEADD_RSV },
327 { SUB_CHIP_ID2, TWL6030_BASEADD_RSV },
328 { SUB_CHIP_ID0, TWL6030_BASEADD_PM_MASTER },
329 { SUB_CHIP_ID0, TWL6030_BASEADD_PM_SLAVE_MISC },
330
331 { SUB_CHIP_ID0, TWL6030_BASEADD_RTC },
332 { SUB_CHIP_ID0, TWL6030_BASEADD_MEM },
333};
334
268/*----------------------------------------------------------------------*/ 335/*----------------------------------------------------------------------*/
269 336
270/* Exported Functions */ 337/* Exported Functions */
@@ -292,7 +359,7 @@ int twl_i2c_write(u8 mod_no, u8 *value, u8 reg, unsigned num_bytes)
292 pr_err("%s: invalid module number %d\n", DRIVER_NAME, mod_no); 359 pr_err("%s: invalid module number %d\n", DRIVER_NAME, mod_no);
293 return -EPERM; 360 return -EPERM;
294 } 361 }
295 sid = twl4030_map[mod_no].sid; 362 sid = twl_map[mod_no].sid;
296 twl = &twl_modules[sid]; 363 twl = &twl_modules[sid];
297 364
298 if (unlikely(!inuse)) { 365 if (unlikely(!inuse)) {
@@ -310,7 +377,7 @@ int twl_i2c_write(u8 mod_no, u8 *value, u8 reg, unsigned num_bytes)
310 msg->flags = 0; 377 msg->flags = 0;
311 msg->buf = value; 378 msg->buf = value;
312 /* over write the first byte of buffer with the register address */ 379 /* over write the first byte of buffer with the register address */
313 *value = twl4030_map[mod_no].base + reg; 380 *value = twl_map[mod_no].base + reg;
314 ret = i2c_transfer(twl->client->adapter, twl->xfer_msg, 1); 381 ret = i2c_transfer(twl->client->adapter, twl->xfer_msg, 1);
315 mutex_unlock(&twl->xfer_lock); 382 mutex_unlock(&twl->xfer_lock);
316 383
@@ -349,7 +416,7 @@ int twl_i2c_read(u8 mod_no, u8 *value, u8 reg, unsigned num_bytes)
349 pr_err("%s: invalid module number %d\n", DRIVER_NAME, mod_no); 416 pr_err("%s: invalid module number %d\n", DRIVER_NAME, mod_no);
350 return -EPERM; 417 return -EPERM;
351 } 418 }
352 sid = twl4030_map[mod_no].sid; 419 sid = twl_map[mod_no].sid;
353 twl = &twl_modules[sid]; 420 twl = &twl_modules[sid];
354 421
355 if (unlikely(!inuse)) { 422 if (unlikely(!inuse)) {
@@ -362,7 +429,7 @@ int twl_i2c_read(u8 mod_no, u8 *value, u8 reg, unsigned num_bytes)
362 msg->addr = twl->address; 429 msg->addr = twl->address;
363 msg->len = 1; 430 msg->len = 1;
364 msg->flags = 0; /* Read the register value */ 431 msg->flags = 0; /* Read the register value */
365 val = twl4030_map[mod_no].base + reg; 432 val = twl_map[mod_no].base + reg;
366 msg->buf = &val; 433 msg->buf = &val;
367 /* [MSG2] fill the data rx buffer */ 434 /* [MSG2] fill the data rx buffer */
368 msg = &twl->xfer_msg[1]; 435 msg = &twl->xfer_msg[1];
@@ -486,6 +553,7 @@ add_regulator_linked(int num, struct regulator_init_data *pdata,
486 struct regulator_consumer_supply *consumers, 553 struct regulator_consumer_supply *consumers,
487 unsigned num_consumers) 554 unsigned num_consumers)
488{ 555{
556 unsigned sub_chip_id;
489 /* regulator framework demands init_data ... */ 557 /* regulator framework demands init_data ... */
490 if (!pdata) 558 if (!pdata)
491 return NULL; 559 return NULL;
@@ -496,7 +564,8 @@ add_regulator_linked(int num, struct regulator_init_data *pdata,
496 } 564 }
497 565
498 /* NOTE: we currently ignore regulator IRQs, e.g. for short circuits */ 566 /* NOTE: we currently ignore regulator IRQs, e.g. for short circuits */
499 return add_numbered_child(3, "twl_reg", num, 567 sub_chip_id = twl_map[TWL_MODULE_PM_MASTER].sid;
568 return add_numbered_child(sub_chip_id, "twl_reg", num,
500 pdata, sizeof(*pdata), false, 0, 0); 569 pdata, sizeof(*pdata), false, 0, 0);
501} 570}
502 571
@@ -516,6 +585,7 @@ static int
516add_children(struct twl4030_platform_data *pdata, unsigned long features) 585add_children(struct twl4030_platform_data *pdata, unsigned long features)
517{ 586{
518 struct device *child; 587 struct device *child;
588 unsigned sub_chip_id;
519 589
520 if (twl_has_bci() && pdata->bci && 590 if (twl_has_bci() && pdata->bci &&
521 !(features & (TPS_SUBSET | TWL5031))) { 591 !(features & (TPS_SUBSET | TWL5031))) {
@@ -561,7 +631,8 @@ add_children(struct twl4030_platform_data *pdata, unsigned long features)
561 * Eventually, Linux might become more aware of such 631 * Eventually, Linux might become more aware of such
562 * HW security concerns, and "least privilege". 632 * HW security concerns, and "least privilege".
563 */ 633 */
564 child = add_child(3, "twl_rtc", 634 sub_chip_id = twl_map[TWL_MODULE_RTC].sid;
635 child = add_child(sub_chip_id, "twl_rtc",
565 NULL, 0, 636 NULL, 0,
566 true, pdata->irq_base + RTC_INTR_OFFSET, 0); 637 true, pdata->irq_base + RTC_INTR_OFFSET, 0);
567 if (IS_ERR(child)) 638 if (IS_ERR(child))
@@ -812,16 +883,22 @@ static void clocks_init(struct device *dev,
812 883
813/*----------------------------------------------------------------------*/ 884/*----------------------------------------------------------------------*/
814 885
815int twl_init_irq(int irq_num, unsigned irq_base, unsigned irq_end); 886int twl4030_init_irq(int irq_num, unsigned irq_base, unsigned irq_end);
816int twl_exit_irq(void); 887int twl4030_exit_irq(void);
817int twl_init_chip_irq(const char *chip); 888int twl4030_init_chip_irq(const char *chip);
889int twl6030_init_irq(int irq_num, unsigned irq_base, unsigned irq_end);
890int twl6030_exit_irq(void);
818 891
819static int twl_remove(struct i2c_client *client) 892static int twl_remove(struct i2c_client *client)
820{ 893{
821 unsigned i; 894 unsigned i;
822 int status; 895 int status;
823 896
824 status = twl_exit_irq(); 897 if (twl_class_is_4030())
898 status = twl4030_exit_irq();
899 else
900 status = twl6030_exit_irq();
901
825 if (status < 0) 902 if (status < 0)
826 return status; 903 return status;
827 904
@@ -878,6 +955,13 @@ twl_probe(struct i2c_client *client, const struct i2c_device_id *id)
878 mutex_init(&twl->xfer_lock); 955 mutex_init(&twl->xfer_lock);
879 } 956 }
880 inuse = true; 957 inuse = true;
958 if ((id->driver_data) & TWL6030_CLASS) {
959 twl_id = TWL6030_CLASS_ID;
960 twl_map = &twl6030_map[0];
961 } else {
962 twl_id = TWL4030_CLASS_ID;
963 twl_map = &twl4030_map[0];
964 }
881 965
882 /* setup clock framework */ 966 /* setup clock framework */
883 clocks_init(&client->dev, pdata->clock); 967 clocks_init(&client->dev, pdata->clock);
@@ -890,8 +974,15 @@ twl_probe(struct i2c_client *client, const struct i2c_device_id *id)
890 if (client->irq 974 if (client->irq
891 && pdata->irq_base 975 && pdata->irq_base
892 && pdata->irq_end > pdata->irq_base) { 976 && pdata->irq_end > pdata->irq_base) {
893 twl_init_chip_irq(id->name); 977 if (twl_class_is_4030()) {
894 status = twl_init_irq(client->irq, pdata->irq_base, pdata->irq_end); 978 twl4030_init_chip_irq(id->name);
979 status = twl4030_init_irq(client->irq, pdata->irq_base,
980 pdata->irq_end);
981 } else {
982 status = twl6030_init_irq(client->irq, pdata->irq_base,
983 pdata->irq_end);
984 }
985
895 if (status < 0) 986 if (status < 0)
896 goto fail; 987 goto fail;
897 } 988 }
@@ -910,6 +1001,7 @@ static const struct i2c_device_id twl_ids[] = {
910 { "tps65950", 0 }, /* catalog version of twl5030 */ 1001 { "tps65950", 0 }, /* catalog version of twl5030 */
911 { "tps65930", TPS_SUBSET }, /* fewer LDOs and DACs; no charger */ 1002 { "tps65930", TPS_SUBSET }, /* fewer LDOs and DACs; no charger */
912 { "tps65920", TPS_SUBSET }, /* fewer LDOs; no codec or charger */ 1003 { "tps65920", TPS_SUBSET }, /* fewer LDOs; no codec or charger */
1004 { "twl6030", TWL6030_CLASS }, /* "Phoenix power chip" */
913 { /* end of list */ }, 1005 { /* end of list */ },
914}; 1006};
915MODULE_DEVICE_TABLE(i2c, twl_ids); 1007MODULE_DEVICE_TABLE(i2c, twl_ids);