diff options
author | Oleksandr Dmytryshyn <oleksandr.dmytryshyn@ti.com> | 2012-01-25 18:20:39 +0200 |
---|---|---|
committer | Ziyann <jaraidaniel@gmail.com> | 2014-10-01 13:00:08 +0200 |
commit | 74bb1cc4aa788e5442109f412b65050a024e18d2 (patch) | |
tree | 36f65db03f670589111ecfeeb532cf1efda78da6 /drivers/mfd | |
parent | 9a8bb91da66c26ec7d1fb2ce3eabf5cb97dfad94 (diff) | |
download | kernel_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.c | 17 | ||||
-rw-r--r-- | drivers/mfd/twl6030-power.c | 178 |
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) |