aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mfd
diff options
context:
space:
mode:
authorOleksandr Dmytryshyn <oleksandr.dmytryshyn@ti.com>2012-01-25 18:20:39 +0200
committerZiyann <jaraidaniel@gmail.com>2014-10-01 13:00:08 +0200
commit74bb1cc4aa788e5442109f412b65050a024e18d2 (patch)
tree36f65db03f670589111ecfeeb532cf1efda78da6 /drivers/mfd
parent9a8bb91da66c26ec7d1fb2ce3eabf5cb97dfad94 (diff)
downloadkernel_samsung_tuna-74bb1cc4aa788e5442109f412b65050a024e18d2.tar.gz
kernel_samsung_tuna-74bb1cc4aa788e5442109f412b65050a024e18d2.tar.bz2
kernel_samsung_tuna-74bb1cc4aa788e5442109f412b65050a024e18d2.zip
OMAP4: MFD: Add resources assignments for the TWL6032
This patch adds definition and initialization of the resources assignments (LDOs, SYSEN, SMPS, etc) for the TWL6032. Change-Id: Icdca2129d0ca552fae8f8b0849489d9d1c77f526 Signed-off-by: Oleksandr Dmytryshyn <oleksandr.dmytryshyn@ti.com>
Diffstat (limited to 'drivers/mfd')
-rw-r--r--drivers/mfd/twl-core.c17
-rw-r--r--drivers/mfd/twl6030-power.c178
2 files changed, 142 insertions, 53 deletions
diff --git a/drivers/mfd/twl-core.c b/drivers/mfd/twl-core.c
index 24c64675b4e..9ab40b5921a 100644
--- a/drivers/mfd/twl-core.c
+++ b/drivers/mfd/twl-core.c
@@ -1332,12 +1332,19 @@ twl_probe(struct i2c_client *client, const struct i2c_device_id *id)
WARN(ret < 0, "Error: reading twl_idcode register value\n");
}
+ features = id->driver_data;
+ if (twl_class_is_6030()) {
+ twl_i2c_read_u8(TWL_MODULE_USB, &temp, USB_PRODUCT_ID_LSB);
+ if (temp == 0x32)
+ features |= TWL6032_SUBCLASS;
+ }
+
/* load power event scripts */
if (twl_has_power()) {
if (twl_class_is_4030() && pdata->power)
twl4030_power_init(pdata->power);
if (twl_class_is_6030())
- twl6030_power_init(pdata->power);
+ twl6030_power_init(pdata->power, features);
}
/* Maybe init the T2 Interrupt subsystem */
@@ -1369,14 +1376,6 @@ twl_probe(struct i2c_client *client, const struct i2c_device_id *id)
twl_i2c_write_u8(TWL4030_MODULE_INTBR, temp, REG_GPPUPDCTR1);
}
-
- features = id->driver_data;
- if (twl_class_is_6030()) {
- twl_i2c_read_u8(TWL_MODULE_USB, &temp, USB_PRODUCT_ID_LSB);
- if (temp == 0x32)
- features |= TWL6032_SUBCLASS;
- }
-
status = add_children(pdata, features);
fail:
if (status < 0)
diff --git a/drivers/mfd/twl6030-power.c b/drivers/mfd/twl6030-power.c
index 84ea1b2cf8f..918b3c26b9a 100644
--- a/drivers/mfd/twl6030-power.c
+++ b/drivers/mfd/twl6030-power.c
@@ -19,6 +19,7 @@
#include <linux/i2c/twl.h>
#include <linux/platform_device.h>
#include <linux/suspend.h>
+#include <linux/string.h>
#include <asm/mach-types.h>
@@ -31,49 +32,91 @@ static u8 dev_on_group;
* struct twl6030_resource_map - describe the resource mapping for TWL6030
* @name: name of the resource
* @res_id: resource ID
- * @base_addr: base address
- * @group: which device group can control this resource?
+ * @base_addr: base address for TWL6030
+ * @base_addr: type of the Resources Assignment register for TWL6032
+ * base_addr = 0 for PREQx_RES_ASS_A register
+ * base_addr = 1 for PREQx_RES_ASS_B register
+ * base_addr = 2 for PREQx_RES_ASS_C register
+ * @group: which device group can control this resource?
+ * @mask: unused for TWL6030
+ * @mask: bit mask of the resource in PREQx_RES_ASS_x registers for TWL6032
*/
struct twl6030_resource_map {
char *name;
u8 res_id;
u8 base_addr;
u8 group;
+ u8 mask;
};
+#define TWL6030_RES_DATA(ID, NAME, BASE_ADDR, GROUP) \
+ {.res_id = ID, .name = NAME, .base_addr = BASE_ADDR,\
+ .group = GROUP, .mask = 0,}
+
+#define TWL6032_RES_DATA(ID, NAME, BASE_ADDR, GROUP, MASK) \
+ {.res_id = ID, .name = NAME, .base_addr = BASE_ADDR,\
+ .group = GROUP, .mask = MASK,}
+
/* list of all s/w modifiable resources in TWL6030 */
static __initdata struct twl6030_resource_map twl6030_res_map[] = {
- {.res_id = RES_V1V29,.name = "V1V29",.base_addr = 0x40,.group = DEV_GRP_P1,},
- {.res_id = RES_V1V8,.name = "V1V8",.base_addr = 0x46,.group = DEV_GRP_P1,},
- {.res_id = RES_V2V1,.name = "V2V1",.base_addr = 0x4c,.group = DEV_GRP_P1,},
- {.res_id = RES_VDD1,.name = "CORE1",.base_addr = 0x52,.group = DEV_GRP_P1,},
- {.res_id = RES_VDD2,.name = "CORE2",.base_addr = 0x58,.group = DEV_GRP_P1,},
- {.res_id = RES_VDD3,.name = "CORE3",.base_addr = 0x5e,.group = DEV_GRP_P1,},
- {.res_id = RES_VMEM,.name = "VMEM",.base_addr = 0x64,.group = DEV_GRP_P1,},
+ TWL6030_RES_DATA(RES_V1V29, "V1V29", 0x40, DEV_GRP_P1),
+ TWL6030_RES_DATA(RES_V1V8, "V1V8", 0x46, DEV_GRP_P1),
+ TWL6030_RES_DATA(RES_V2V1, "V2V1", 0x4c, DEV_GRP_P1),
+ TWL6030_RES_DATA(RES_VDD1, "CORE1", 0x52, DEV_GRP_P1),
+ TWL6030_RES_DATA(RES_VDD2, "CORE2", 0x58, DEV_GRP_P1),
+ TWL6030_RES_DATA(RES_VDD3, "CORE3", 0x5e, DEV_GRP_P1),
+ TWL6030_RES_DATA(RES_VMEM, "VMEM", 0x64, DEV_GRP_P1),
/* VANA cannot be modified */
- {.res_id = RES_VUAX1,.name = "VUAX1",.base_addr = 0x84,.group = DEV_GRP_P1,},
- {.res_id = RES_VAUX2,.name = "VAUX2",.base_addr = 0x88,.group = DEV_GRP_P1,},
- {.res_id = RES_VAUX3,.name = "VAUX3",.base_addr = 0x8c,.group = DEV_GRP_P1,},
- {.res_id = RES_VCXIO,.name = "VCXIO",.base_addr = 0x90,.group = DEV_GRP_P1,},
- {.res_id = RES_VDAC,.name = "VDAC",.base_addr = 0x94,.group = DEV_GRP_P1,},
- {.res_id = RES_VMMC1,.name = "VMMC",.base_addr = 0x98,.group = DEV_GRP_P1,},
- {.res_id = RES_VPP,.name = "VPP",.base_addr = 0x9c,.group = DEV_GRP_P1,},
+ TWL6030_RES_DATA(RES_VUAX1, "VUAX1", 0x84, DEV_GRP_P1),
+ TWL6030_RES_DATA(RES_VAUX2, "VAUX2", 0x88, DEV_GRP_P1),
+ TWL6030_RES_DATA(RES_VAUX3, "VAUX3", 0x8c, DEV_GRP_P1),
+ TWL6030_RES_DATA(RES_VCXIO, "VCXIO", 0x90, DEV_GRP_P1),
+ TWL6030_RES_DATA(RES_VDAC, "VDAC", 0x94, DEV_GRP_P1),
+ TWL6030_RES_DATA(RES_VMMC1, "VMMC", 0x98, DEV_GRP_P1),
+ TWL6030_RES_DATA(RES_VPP, "VPP", 0x9c, DEV_GRP_P1),
/* VRTC cannot be modified */
- {.res_id = RES_VUSBCP,.name = "VUSB",.base_addr = 0xa0,.group = DEV_GRP_P1,},
- {.res_id = RES_VSIM,.name = "VSIM",.base_addr = 0xa4,.group = DEV_GRP_P1,},
- {.res_id = RES_REGEN,.name = "REGEN1",.base_addr = 0xad,.group = DEV_GRP_P1,},
- {.res_id = RES_REGEN2,.name = "REGEN2",.base_addr = 0xb0,.group = DEV_GRP_P1,},
- {.res_id = RES_SYSEN,.name = "SYSEN",.base_addr = 0xb3,.group = DEV_GRP_P1,},
+ TWL6030_RES_DATA(RES_VUSBCP, "VUSB", 0xa0, DEV_GRP_P1),
+ TWL6030_RES_DATA(RES_VSIM, "VSIM", 0xa4, DEV_GRP_P1),
+ TWL6030_RES_DATA(RES_REGEN, "REGEN1", 0xad, DEV_GRP_P1),
+ TWL6030_RES_DATA(RES_REGEN2, "REGEN2", 0xb0, DEV_GRP_P1),
+ TWL6030_RES_DATA(RES_SYSEN, "SYSEN", 0xb3, DEV_GRP_P1),
/* NRES_PWRON cannot be modified */
/* 32KCLKAO cannot be modified */
- {.res_id = RES_32KCLKG,.name = "32KCLKG",.base_addr = 0xbc,.group = DEV_GRP_P1,},
- {.res_id = RES_32KCLKAUDIO,.name = "32KCLKAUDIO",.base_addr = 0xbf,.group = DEV_GRP_P1,},
+ TWL6030_RES_DATA(RES_32KCLKG, "32KCLKG", 0xbc, DEV_GRP_P1),
+ TWL6030_RES_DATA(RES_32KCLKAUDIO, "32KCLKAUDIO", 0xbf, DEV_GRP_P1),
/* BIAS cannot be modified */
/* VBATMIN_HI cannot be modified */
/* RC6MHZ cannot be modified */
/* TEMP cannot be modified */
};
+/* list of all s/w modifiable resources in TWL6032 */
+static __initdata struct twl6030_resource_map twl6032_res_map[] = {
+ /* PREQx_RES_ASS_A register resources */
+ TWL6032_RES_DATA(RES_LDOUSB, "VUSB", 0, DEV_GRP_P1, BIT(5)),
+ TWL6032_RES_DATA(RES_SMPS5, "SMPS5", 0, DEV_GRP_P1, BIT(4)),
+ TWL6032_RES_DATA(RES_SMPS5, "SMPS4", 0, DEV_GRP_P1, BIT(3)),
+ TWL6032_RES_DATA(RES_SMPS5, "SMPS3", 0, DEV_GRP_P1, BIT(2)),
+ TWL6032_RES_DATA(RES_SMPS5, "SMPS2", 0, DEV_GRP_P1, BIT(1)),
+ TWL6032_RES_DATA(RES_SMPS5, "SMPS1", 0, DEV_GRP_P1, BIT(0)),
+ /* PREQx_RES_ASS_B register resources */
+ TWL6032_RES_DATA(RES_LDOLN, "LDOLN", 1, DEV_GRP_P1, BIT(7)),
+ TWL6032_RES_DATA(RES_LDO7, "LDO7", 1, DEV_GRP_P1, BIT(6)),
+ TWL6032_RES_DATA(RES_LDO6, "LDO6", 1, DEV_GRP_P1, BIT(5)),
+ TWL6032_RES_DATA(RES_LDO5, "LDO5", 1, DEV_GRP_P1, BIT(4)),
+ TWL6032_RES_DATA(RES_LDO4, "LDO4", 1, DEV_GRP_P1, BIT(3)),
+ TWL6032_RES_DATA(RES_LDO3, "LDO3", 1, DEV_GRP_P1, BIT(2)),
+ TWL6032_RES_DATA(RES_LDO2, "LDO2", 1, DEV_GRP_P1, BIT(1)),
+ TWL6032_RES_DATA(RES_LDO1, "LDO1", 1, DEV_GRP_P1, BIT(0)),
+ /* PREQx_RES_ASS_C register resources */
+ TWL6032_RES_DATA(RES_VSYSMIN_HI, "VSYSMIN_HI", 2, DEV_GRP_P1, BIT(5)),
+ TWL6032_RES_DATA(RES_32KCLKG, "32KCLKG", 2, DEV_GRP_P1, BIT(4)),
+ TWL6032_RES_DATA(RES_32KCLKAUDIO, "32KCLKAUDIO", 2, DEV_GRP_P1, BIT(3)),
+ TWL6032_RES_DATA(RES_SYSEN, "SYSEN", 2, DEV_GRP_P1, BIT(2)),
+ TWL6032_RES_DATA(RES_REGEN2, "REGEN2", 2, DEV_GRP_P1, BIT(1)),
+ TWL6032_RES_DATA(RES_REGEN, "REGEN1", 2, DEV_GRP_P1, BIT(0)),
+};
+
static struct twl4030_system_config twl6030_sys_config[] = {
{.name = "DEV_ON", .group = DEV_GRP_P1,},
};
@@ -148,26 +191,64 @@ static __init void twl6030_process_system_config(void)
}
}
-static __init void twl6030_program_map(void)
+#define DEV_GRP_P1_OFFSET 1
+#define DEV_GRP_P2_OFFSET 4
+#define DEV_GRP_P3_OFFSET 7
+
+static __init void twl6030_program_map(unsigned long features)
{
- struct twl6030_resource_map *res = twl6030_res_map;
+ struct twl6030_resource_map *res;
int r, i;
- for (i = 0; i < ARRAY_SIZE(twl6030_res_map); i++) {
- u8 grp = 0;
+ if (features & TWL6032_SUBCLASS) {
+ /**
+ * mask[0] = 0 for twl_i2c_write
+ * mask[1]-mask[3]: PREQ1_RES_ASS_A - PREQ1_RES_ASS_C
+ * mask[4]-mask[6]: PREQ2_RES_ASS_A - PREQ2_RES_ASS_C
+ * mask[7]-mask[9]: PREQ3_RES_ASS_A - PREQ3_RES_ASS_C
+ */
+ u8 mask[10];
+
+ res = twl6032_res_map;
+ memset(&mask[0], 0, 10);
+
+ for (i = 0; i < ARRAY_SIZE(twl6032_res_map); i++) {
+ /* map back from generic device id to TWL6032 mask */
+ mask[DEV_GRP_P1_OFFSET + res->base_addr] |= \
+ (res->group & DEV_GRP_P1) ? res->mask : 0;
+ mask[DEV_GRP_P2_OFFSET + res->base_addr] |= \
+ (res->group & DEV_GRP_P2) ? res->mask : 0;
+ mask[DEV_GRP_P3_OFFSET + res->base_addr] |= \
+ (res->group & DEV_GRP_P3) ? res->mask : 0;
+ res++;
+ }
- /* map back from generic device id to TWL6030 ID */
- grp |= (res->group & DEV_GRP_P1) ? P1_GRP_6030 : 0;
- grp |= (res->group & DEV_GRP_P2) ? P2_GRP_6030 : 0;
- grp |= (res->group & DEV_GRP_P3) ? P3_GRP_6030 : 0;
+ r = twl_i2c_write(TWL6030_MODULE_ID0, &mask[0],
+ TWL6032_PREQ1_RES_ASS_A, 9);
- r = twl_i2c_write_u8(TWL6030_MODULE_ID0, res->group,
- res->base_addr);
if (r)
- pr_err("%s: Error(%d) programming map %s {addr=0x%02x},"
- "grp=0x%02X\n", __func__, r, res->name,
- res->base_addr, res->group);
- res++;
+ pr_err("%s: Error(%d) programming TWL6032 PREQ "
+ "Assignment Registers {start addr=0xd7}\n",
+ __func__, r);
+ } else {
+ res = twl6030_res_map;
+ for (i = 0; i < ARRAY_SIZE(twl6030_res_map); i++) {
+ u8 grp = 0;
+
+ /* map back from generic device id to TWL6030 ID */
+ grp |= (res->group & DEV_GRP_P1) ? P1_GRP_6030 : 0;
+ grp |= (res->group & DEV_GRP_P2) ? P2_GRP_6030 : 0;
+ grp |= (res->group & DEV_GRP_P3) ? P3_GRP_6030 : 0;
+
+ r = twl_i2c_write_u8(TWL6030_MODULE_ID0, res->group,
+ res->base_addr);
+ if (r)
+ pr_err("%s: Error(%d) programming map %s {"
+ "addr=0x%02x},grp=0x%02X\n", __func__,
+ r, res->name, res->base_addr,
+ res->group);
+ res++;
+ }
}
}
@@ -189,14 +270,22 @@ static __init void twl6030_update_system_map
}
}
-static __init void twl6030_update_map(struct twl4030_resconfig *res_list)
+static __init void twl6030_update_map(struct twl4030_resconfig *res_list, \
+ unsigned long features)
{
int i, res_idx = 0;
struct twl6030_resource_map *res;
+ struct twl6030_resource_map *cur_twl6030_res = twl6030_res_map;
+ int twl6030_res_cnt = ARRAY_SIZE(twl6030_res_map);
+
+ if (features & TWL6032_SUBCLASS) {
+ cur_twl6030_res = twl6032_res_map;
+ twl6030_res_cnt = ARRAY_SIZE(twl6032_res_map);
+ }
while (res_list->resource != TWL4030_RESCONFIG_UNDEF) {
- res = twl6030_res_map;
- for (i = 0; i < ARRAY_SIZE(twl6030_res_map); i++) {
+ res = cur_twl6030_res;
+ for (i = 0; i < twl6030_res_cnt; i++) {
if (res->res_id == res_list->resource) {
res->group = res_list->devgroup &
(DEV_GRP_P1 | DEV_GRP_P2 | DEV_GRP_P3);
@@ -205,7 +294,7 @@ static __init void twl6030_update_map(struct twl4030_resconfig *res_list)
res++;
}
- if (i == ARRAY_SIZE(twl6030_res_map)) {
+ if (i == twl6030_res_cnt) {
pr_err("%s: in platform_data resource index %d, cannot"
" find match for resource 0x%02x. NO Update!\n",
__func__, res_idx, res_list->resource);
@@ -243,7 +332,8 @@ static struct notifier_block twl6030_power_pm_notifier = {
* @power_data: power resource map to update (OPTIONAL) - use this if a resource
* is used by other devices other than APP (DEV_GRP_P1)
*/
-void __init twl6030_power_init(struct twl4030_power_data *power_data)
+void __init twl6030_power_init(struct twl4030_power_data *power_data, \
+ unsigned long features)
{
int r;
@@ -255,14 +345,14 @@ void __init twl6030_power_init(struct twl4030_power_data *power_data)
}
if (power_data && power_data->resource_config)
- twl6030_update_map(power_data->resource_config);
+ twl6030_update_map(power_data->resource_config, features);
if (power_data && power_data->sys_config)
twl6030_update_system_map(power_data->sys_config);
twl6030_process_system_config();
- twl6030_program_map();
+ twl6030_program_map(features);
r = register_pm_notifier(&twl6030_power_pm_notifier);
if (r)