2012-11-13 08:29:01

by Peter Ujfalusi

[permalink] [raw]
Subject: [PATCH 00/13] MFD: twl drivers: Convert to regmap IO and cleanups

Hello,

This series converts the twl-core to use regmap for IO towards the chip.
With the conversion to regmap IO we no longer need to allocate bigger buffer for
writes.
I have appended patches to this series to make some cleanups which will help in
the future to further clean up the twl stack.

The series depends on a regression fix patch for the twl-core:
https://patchwork.kernel.org/patch/1679421/

Regards,
Peter
---
Peter Ujfalusi (13):
MFD: twl-core: Register twl4030-madc child only for twl4030 class
MFD: twl-core: Support for proper PWM drivers
MFD: twl-core: Convert to use regmap for I/O
MFD/rtc/gpio: twl: No need to allocate bigger buffer for write
MFD: twl-core: Clean up and correct child registration
mfd: twl: Remove unused TWL_MODULE definitions
mfd: twl: Convert module id definitions to enums
mfd: twl: Use decimal numbers for TWL6030_MODULE_IDs
MFD: twl-core: re-group the twl_mapping table for easier reading
mfd: twl4030-madc: Change TWL4030_MODULE_* ids to TWL_MODULE_*
mfd: twl4030-power: Change TWL4030_MODULE_* ids to TWL_MODULE_*
mfd: twl4030-irq: Change TWL4030_MODULE_* ids to TWL_MODULE_*
mfd: twl-core: Change TWL4030_MODULE_* ids to TWL_MODULE_*

drivers/gpio/gpio-twl4030.c | 12 +--
drivers/mfd/twl-core.c | 227 +++++++++++++++++++++++---------------------
drivers/mfd/twl4030-irq.c | 10 +-
drivers/mfd/twl4030-madc.c | 14 +--
drivers/mfd/twl4030-power.c | 124 ++++++++++--------------
drivers/mfd/twl6030-irq.c | 4 +-
drivers/rtc/rtc-twl.c | 32 +++----
include/linux/i2c/twl.h | 73 +++++++-------
8 files changed, 241 insertions(+), 255 deletions(-)

--
1.8.0


2012-11-13 08:29:03

by Peter Ujfalusi

[permalink] [raw]
Subject: [PATCH 01/13] MFD: twl-core: Register twl4030-madc child only for twl4030 class

twl4030-madc driver can only handle twl4030 class MADC. The newer revisions
of twl does not have MADC, instead they have different IP called GPADC which
is not backward compatible.

Signed-off-by: Peter Ujfalusi <[email protected]>
---
drivers/mfd/twl-core.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/mfd/twl-core.c b/drivers/mfd/twl-core.c
index a071a86..d7577cb 100644
--- a/drivers/mfd/twl-core.c
+++ b/drivers/mfd/twl-core.c
@@ -646,7 +646,8 @@ add_children(struct twl4030_platform_data *pdata, unsigned irq_base,
return PTR_ERR(child);
}

- if (IS_ENABLED(CONFIG_TWL4030_MADC) && pdata->madc) {
+ if (IS_ENABLED(CONFIG_TWL4030_MADC) && pdata->madc &&
+ twl_class_is_4030()) {
child = add_child(2, "twl4030_madc",
pdata->madc, sizeof(*pdata->madc),
true, irq_base + MADC_INTR_OFFSET, 0);
--
1.8.0

2012-11-13 08:29:11

by Peter Ujfalusi

[permalink] [raw]
Subject: [PATCH 08/13] mfd: twl: Use decimal numbers for TWL6030_MODULE_IDs

It is easier fro humans to understand decimal numbers than hexadecimals when
they are used as indexes.

Signed-off-by: Peter Ujfalusi <[email protected]>
---
include/linux/i2c/twl.h | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/include/linux/i2c/twl.h b/include/linux/i2c/twl.h
index b1c44cc..1ff54b1 100644
--- a/include/linux/i2c/twl.h
+++ b/include/linux/i2c/twl.h
@@ -81,9 +81,9 @@ enum twl4030_module_ids {
#define TWL_MODULE_PWM TWL4030_MODULE_PWM0
#define TWL_MODULE_LED TWL4030_MODULE_LED

-#define TWL6030_MODULE_ID0 0x0D
-#define TWL6030_MODULE_ID1 0x0E
-#define TWL6030_MODULE_ID2 0x0F
+#define TWL6030_MODULE_ID0 13
+#define TWL6030_MODULE_ID1 14
+#define TWL6030_MODULE_ID2 15

#define GPIO_INTR_OFFSET 0
#define KEYPAD_INTR_OFFSET 1
--
1.8.0

2012-11-13 08:29:16

by Peter Ujfalusi

[permalink] [raw]
Subject: [PATCH 11/13] mfd: twl4030-power: Change TWL4030_MODULE_* ids to TWL_MODULE_*

To facilitate upcoming cleanup in twl stack.
No functional changes.

Signed-off-by: Peter Ujfalusi <[email protected]>
---
drivers/mfd/twl4030-power.c | 124 ++++++++++++++++++--------------------------
1 file changed, 51 insertions(+), 73 deletions(-)

diff --git a/drivers/mfd/twl4030-power.c b/drivers/mfd/twl4030-power.c
index 79ca33d..4fda77c 100644
--- a/drivers/mfd/twl4030-power.c
+++ b/drivers/mfd/twl4030-power.c
@@ -128,12 +128,10 @@ static int __devinit twl4030_write_script_byte(u8 address, u8 byte)
{
int err;

- err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, address,
- R_MEMORY_ADDRESS);
+ err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, address, R_MEMORY_ADDRESS);
if (err)
goto out;
- err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, byte,
- R_MEMORY_DATA);
+ err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, byte, R_MEMORY_DATA);
out:
return err;
}
@@ -189,19 +187,16 @@ static int __devinit twl4030_config_wakeup3_sequence(u8 address)
u8 data;

/* Set SLEEP to ACTIVE SEQ address for P3 */
- err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, address,
- R_SEQ_ADD_S2A3);
+ err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, address, R_SEQ_ADD_S2A3);
if (err)
goto out;

/* P3 LVL_WAKEUP should be on LEVEL */
- err = twl_i2c_read_u8(TWL4030_MODULE_PM_MASTER, &data,
- R_P3_SW_EVENTS);
+ err = twl_i2c_read_u8(TWL_MODULE_PM_MASTER, &data, R_P3_SW_EVENTS);
if (err)
goto out;
data |= LVL_WAKEUP;
- err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, data,
- R_P3_SW_EVENTS);
+ err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, data, R_P3_SW_EVENTS);
out:
if (err)
pr_err("TWL4030 wakeup sequence for P3 config error\n");
@@ -214,43 +209,38 @@ static int __devinit twl4030_config_wakeup12_sequence(u8 address)
u8 data;

/* Set SLEEP to ACTIVE SEQ address for P1 and P2 */
- err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, address,
- R_SEQ_ADD_S2A12);
+ err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, address, R_SEQ_ADD_S2A12);
if (err)
goto out;

/* P1/P2 LVL_WAKEUP should be on LEVEL */
- err = twl_i2c_read_u8(TWL4030_MODULE_PM_MASTER, &data,
- R_P1_SW_EVENTS);
+ err = twl_i2c_read_u8(TWL_MODULE_PM_MASTER, &data, R_P1_SW_EVENTS);
if (err)
goto out;

data |= LVL_WAKEUP;
- err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, data,
- R_P1_SW_EVENTS);
+ err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, data, R_P1_SW_EVENTS);
if (err)
goto out;

- err = twl_i2c_read_u8(TWL4030_MODULE_PM_MASTER, &data,
- R_P2_SW_EVENTS);
+ err = twl_i2c_read_u8(TWL_MODULE_PM_MASTER, &data, R_P2_SW_EVENTS);
if (err)
goto out;

data |= LVL_WAKEUP;
- err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, data,
- R_P2_SW_EVENTS);
+ err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, data, R_P2_SW_EVENTS);
if (err)
goto out;

if (machine_is_omap_3430sdp() || machine_is_omap_ldp()) {
/* Disabling AC charger effect on sleep-active transitions */
- err = twl_i2c_read_u8(TWL4030_MODULE_PM_MASTER, &data,
- R_CFG_P1_TRANSITION);
+ err = twl_i2c_read_u8(TWL_MODULE_PM_MASTER, &data,
+ R_CFG_P1_TRANSITION);
if (err)
goto out;
data &= ~(1<<1);
- err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, data ,
- R_CFG_P1_TRANSITION);
+ err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, data,
+ R_CFG_P1_TRANSITION);
if (err)
goto out;
}
@@ -267,8 +257,7 @@ static int __devinit twl4030_config_sleep_sequence(u8 address)
int err;

/* Set ACTIVE to SLEEP SEQ address in T2 memory*/
- err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, address,
- R_SEQ_ADD_A2S);
+ err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, address, R_SEQ_ADD_A2S);

if (err)
pr_err("TWL4030 sleep sequence config error\n");
@@ -282,42 +271,35 @@ static int __devinit twl4030_config_warmreset_sequence(u8 address)
u8 rd_data;

/* Set WARM RESET SEQ address for P1 */
- err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, address,
- R_SEQ_ADD_WARM);
+ err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, address, R_SEQ_ADD_WARM);
if (err)
goto out;

/* P1/P2/P3 enable WARMRESET */
- err = twl_i2c_read_u8(TWL4030_MODULE_PM_MASTER, &rd_data,
- R_P1_SW_EVENTS);
+ err = twl_i2c_read_u8(TWL_MODULE_PM_MASTER, &rd_data, R_P1_SW_EVENTS);
if (err)
goto out;

rd_data |= ENABLE_WARMRESET;
- err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, rd_data,
- R_P1_SW_EVENTS);
+ err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, rd_data, R_P1_SW_EVENTS);
if (err)
goto out;

- err = twl_i2c_read_u8(TWL4030_MODULE_PM_MASTER, &rd_data,
- R_P2_SW_EVENTS);
+ err = twl_i2c_read_u8(TWL_MODULE_PM_MASTER, &rd_data, R_P2_SW_EVENTS);
if (err)
goto out;

rd_data |= ENABLE_WARMRESET;
- err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, rd_data,
- R_P2_SW_EVENTS);
+ err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, rd_data, R_P2_SW_EVENTS);
if (err)
goto out;

- err = twl_i2c_read_u8(TWL4030_MODULE_PM_MASTER, &rd_data,
- R_P3_SW_EVENTS);
+ err = twl_i2c_read_u8(TWL_MODULE_PM_MASTER, &rd_data, R_P3_SW_EVENTS);
if (err)
goto out;

rd_data |= ENABLE_WARMRESET;
- err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, rd_data,
- R_P3_SW_EVENTS);
+ err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, rd_data, R_P3_SW_EVENTS);
out:
if (err)
pr_err("TWL4030 warmreset seq config error\n");
@@ -341,7 +323,7 @@ static int __devinit twl4030_configure_resource(struct twl4030_resconfig *rconfi
rconfig_addr = res_config_addrs[rconfig->resource];

/* Set resource group */
- err = twl_i2c_read_u8(TWL4030_MODULE_PM_RECEIVER, &grp,
+ err = twl_i2c_read_u8(TWL_MODULE_PM_RECEIVER, &grp,
rconfig_addr + DEV_GRP_OFFSET);
if (err) {
pr_err("TWL4030 Resource %d group could not be read\n",
@@ -352,7 +334,7 @@ static int __devinit twl4030_configure_resource(struct twl4030_resconfig *rconfi
if (rconfig->devgroup != TWL4030_RESCONFIG_UNDEF) {
grp &= ~DEV_GRP_MASK;
grp |= rconfig->devgroup << DEV_GRP_SHIFT;
- err = twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER,
+ err = twl_i2c_write_u8(TWL_MODULE_PM_RECEIVER,
grp, rconfig_addr + DEV_GRP_OFFSET);
if (err < 0) {
pr_err("TWL4030 failed to program devgroup\n");
@@ -361,7 +343,7 @@ static int __devinit twl4030_configure_resource(struct twl4030_resconfig *rconfi
}

/* Set resource types */
- err = twl_i2c_read_u8(TWL4030_MODULE_PM_RECEIVER, &type,
+ err = twl_i2c_read_u8(TWL_MODULE_PM_RECEIVER, &type,
rconfig_addr + TYPE_OFFSET);
if (err < 0) {
pr_err("TWL4030 Resource %d type could not be read\n",
@@ -379,7 +361,7 @@ static int __devinit twl4030_configure_resource(struct twl4030_resconfig *rconfi
type |= rconfig->type2 << TYPE2_SHIFT;
}

- err = twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER,
+ err = twl_i2c_write_u8(TWL_MODULE_PM_RECEIVER,
type, rconfig_addr + TYPE_OFFSET);
if (err < 0) {
pr_err("TWL4030 failed to program resource type\n");
@@ -387,7 +369,7 @@ static int __devinit twl4030_configure_resource(struct twl4030_resconfig *rconfi
}

/* Set remap states */
- err = twl_i2c_read_u8(TWL4030_MODULE_PM_RECEIVER, &remap,
+ err = twl_i2c_read_u8(TWL_MODULE_PM_RECEIVER, &remap,
rconfig_addr + REMAP_OFFSET);
if (err < 0) {
pr_err("TWL4030 Resource %d remap could not be read\n",
@@ -405,7 +387,7 @@ static int __devinit twl4030_configure_resource(struct twl4030_resconfig *rconfi
remap |= rconfig->remap_sleep << SLEEP_STATE_SHIFT;
}

- err = twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER,
+ err = twl_i2c_write_u8(TWL_MODULE_PM_RECEIVER,
remap,
rconfig_addr + REMAP_OFFSET);
if (err < 0) {
@@ -463,49 +445,47 @@ int twl4030_remove_script(u8 flags)
{
int err = 0;

- err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER,
- TWL4030_PM_MASTER_KEY_CFG1,
- TWL4030_PM_MASTER_PROTECT_KEY);
+ err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, TWL4030_PM_MASTER_KEY_CFG1,
+ TWL4030_PM_MASTER_PROTECT_KEY);
if (err) {
pr_err("twl4030: unable to unlock PROTECT_KEY\n");
return err;
}

- err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER,
- TWL4030_PM_MASTER_KEY_CFG2,
- TWL4030_PM_MASTER_PROTECT_KEY);
+ err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, TWL4030_PM_MASTER_KEY_CFG2,
+ TWL4030_PM_MASTER_PROTECT_KEY);
if (err) {
pr_err("twl4030: unable to unlock PROTECT_KEY\n");
return err;
}

if (flags & TWL4030_WRST_SCRIPT) {
- err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, END_OF_SCRIPT,
- R_SEQ_ADD_WARM);
+ err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, END_OF_SCRIPT,
+ R_SEQ_ADD_WARM);
if (err)
return err;
}
if (flags & TWL4030_WAKEUP12_SCRIPT) {
- err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, END_OF_SCRIPT,
- R_SEQ_ADD_S2A12);
+ err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, END_OF_SCRIPT,
+ R_SEQ_ADD_S2A12);
if (err)
return err;
}
if (flags & TWL4030_WAKEUP3_SCRIPT) {
- err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, END_OF_SCRIPT,
- R_SEQ_ADD_S2A3);
+ err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, END_OF_SCRIPT,
+ R_SEQ_ADD_S2A3);
if (err)
return err;
}
if (flags & TWL4030_SLEEP_SCRIPT) {
- err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, END_OF_SCRIPT,
- R_SEQ_ADD_A2S);
+ err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, END_OF_SCRIPT,
+ R_SEQ_ADD_A2S);
if (err)
return err;
}

- err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, 0,
- TWL4030_PM_MASTER_PROTECT_KEY);
+ err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, 0,
+ TWL4030_PM_MASTER_PROTECT_KEY);
if (err)
pr_err("TWL4030 Unable to relock registers\n");

@@ -521,7 +501,7 @@ void twl4030_power_off(void)
{
int err;

- err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, PWR_DEVOFF,
+ err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, PWR_DEVOFF,
TWL4030_PM_MASTER_P1_SW_EVENTS);
if (err)
pr_err("TWL4030 Unable to power off\n");
@@ -534,15 +514,13 @@ void __devinit twl4030_power_init(struct twl4030_power_data *twl4030_scripts)
struct twl4030_resconfig *resconfig;
u8 val, address = twl4030_start_script_address;

- err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER,
- TWL4030_PM_MASTER_KEY_CFG1,
- TWL4030_PM_MASTER_PROTECT_KEY);
+ err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, TWL4030_PM_MASTER_KEY_CFG1,
+ TWL4030_PM_MASTER_PROTECT_KEY);
if (err)
goto unlock;

- err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER,
- TWL4030_PM_MASTER_KEY_CFG2,
- TWL4030_PM_MASTER_PROTECT_KEY);
+ err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, TWL4030_PM_MASTER_KEY_CFG2,
+ TWL4030_PM_MASTER_PROTECT_KEY);
if (err)
goto unlock;

@@ -567,14 +545,14 @@ void __devinit twl4030_power_init(struct twl4030_power_data *twl4030_scripts)
/* Board has to be wired properly to use this feature */
if (twl4030_scripts->use_poweroff && !pm_power_off) {
/* Default for SEQ_OFFSYNC is set, lets ensure this */
- err = twl_i2c_read_u8(TWL4030_MODULE_PM_MASTER, &val,
+ err = twl_i2c_read_u8(TWL_MODULE_PM_MASTER, &val,
TWL4030_PM_MASTER_CFG_P123_TRANSITION);
if (err) {
pr_warning("TWL4030 Unable to read registers\n");

} else if (!(val & SEQ_OFFSYNC)) {
val |= SEQ_OFFSYNC;
- err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, val,
+ err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, val,
TWL4030_PM_MASTER_CFG_P123_TRANSITION);
if (err) {
pr_err("TWL4030 Unable to setup SEQ_OFFSYNC\n");
@@ -586,8 +564,8 @@ void __devinit twl4030_power_init(struct twl4030_power_data *twl4030_scripts)
}

relock:
- err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, 0,
- TWL4030_PM_MASTER_PROTECT_KEY);
+ err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, 0,
+ TWL4030_PM_MASTER_PROTECT_KEY);
if (err)
pr_err("TWL4030 Unable to relock registers\n");
return;
--
1.8.0

2012-11-13 08:29:14

by Peter Ujfalusi

[permalink] [raw]
Subject: [PATCH 07/13] mfd: twl: Convert module id definitions to enums

Use enum list for the module definitions (TWL4030_MODULE_*) which will ease
up future work with the IDs.
At the same time group the IDs in block of five so it is easier to find the
ID we are looking for (to count the number they stand for).

At the same time define TWL_MODULE_LED so client drivers can switch to use
it as soon as it is possible.

Signed-off-by: Peter Ujfalusi <[email protected]>
---
drivers/mfd/twl-core.c | 9 +++----
include/linux/i2c/twl.h | 65 +++++++++++++++++++++++++------------------------
2 files changed, 36 insertions(+), 38 deletions(-)

diff --git a/drivers/mfd/twl-core.c b/drivers/mfd/twl-core.c
index d666c9d..bb33b52 100644
--- a/drivers/mfd/twl-core.c
+++ b/drivers/mfd/twl-core.c
@@ -66,9 +66,6 @@

/* Triton Core internal information (BEGIN) */

-/* Last - for index max*/
-#define TWL4030_MODULE_LAST TWL4030_MODULE_SECURED_REG
-
#define TWL_NUM_SLAVES 4

#define SUB_CHIP_ID0 0
@@ -184,7 +181,7 @@ struct twl_mapping {
};
static struct twl_mapping *twl_map;

-static struct twl_mapping twl4030_map[TWL4030_MODULE_LAST + 1] = {
+static struct twl_mapping twl4030_map[] = {
/*
* NOTE: don't change this table without updating the
* <linux/i2c/twl.h> defines for TWL4030_MODULE_*
@@ -327,7 +324,7 @@ int twl_i2c_write(u8 mod_no, u8 *value, u8 reg, unsigned num_bytes)
int sid;
struct twl_client *twl;

- if (unlikely(mod_no > TWL_MODULE_LAST)) {
+ if (unlikely(mod_no >= TWL_MODULE_LAST)) {
pr_err("%s: invalid module number %d\n", DRIVER_NAME, mod_no);
return -EPERM;
}
@@ -369,7 +366,7 @@ int twl_i2c_read(u8 mod_no, u8 *value, u8 reg, unsigned num_bytes)
int sid;
struct twl_client *twl;

- if (unlikely(mod_no > TWL_MODULE_LAST)) {
+ if (unlikely(mod_no >= TWL_MODULE_LAST)) {
pr_err("%s: invalid module number %d\n", DRIVER_NAME, mod_no);
return -EPERM;
}
diff --git a/include/linux/i2c/twl.h b/include/linux/i2c/twl.h
index 7278c72..b1c44cc 100644
--- a/include/linux/i2c/twl.h
+++ b/include/linux/i2c/twl.h
@@ -39,39 +39,39 @@
* address each module uses within a given i2c slave.
*/

-/* Slave 0 (i2c address 0x48) */
-#define TWL4030_MODULE_USB 0x00
-
-/* Slave 1 (i2c address 0x49) */
-#define TWL4030_MODULE_AUDIO_VOICE 0x01
-#define TWL4030_MODULE_GPIO 0x02
-#define TWL4030_MODULE_INTBR 0x03
-#define TWL4030_MODULE_PIH 0x04
-#define TWL4030_MODULE_TEST 0x05
-
-/* Slave 2 (i2c address 0x4a) */
-#define TWL4030_MODULE_KEYPAD 0x06
-#define TWL4030_MODULE_MADC 0x07
-#define TWL4030_MODULE_INTERRUPTS 0x08
-#define TWL4030_MODULE_LED 0x09
-#define TWL4030_MODULE_MAIN_CHARGE 0x0A
-#define TWL4030_MODULE_PRECHARGE 0x0B
-#define TWL4030_MODULE_PWM0 0x0C
-#define TWL4030_MODULE_PWM1 0x0D
-#define TWL4030_MODULE_PWMA 0x0E
-#define TWL4030_MODULE_PWMB 0x0F
-
-#define TWL5031_MODULE_ACCESSORY 0x10
-#define TWL5031_MODULE_INTERRUPTS 0x11
-
-/* Slave 3 (i2c address 0x4b) */
-#define TWL4030_MODULE_BACKUP 0x12
-#define TWL4030_MODULE_INT 0x13
-#define TWL4030_MODULE_PM_MASTER 0x14
-#define TWL4030_MODULE_PM_RECEIVER 0x15
-#define TWL4030_MODULE_RTC 0x16
-#define TWL4030_MODULE_SECURED_REG 0x17
+enum twl4030_module_ids {
+ TWL4030_MODULE_USB = 0, /* Slave 0 (i2c address 0x48) */
+ TWL4030_MODULE_AUDIO_VOICE, /* Slave 1 (i2c address 0x49) */
+ TWL4030_MODULE_GPIO,
+ TWL4030_MODULE_INTBR,
+ TWL4030_MODULE_PIH,
+
+ TWL4030_MODULE_TEST,
+ TWL4030_MODULE_KEYPAD, /* Slave 2 (i2c address 0x4a) */
+ TWL4030_MODULE_MADC,
+ TWL4030_MODULE_INTERRUPTS,
+ TWL4030_MODULE_LED,
+
+ TWL4030_MODULE_MAIN_CHARGE,
+ TWL4030_MODULE_PRECHARGE,
+ TWL4030_MODULE_PWM0,
+ TWL4030_MODULE_PWM1,
+ TWL4030_MODULE_PWMA,
+
+ TWL4030_MODULE_PWMB,
+ TWL5031_MODULE_ACCESSORY,
+ TWL5031_MODULE_INTERRUPTS,
+ TWL4030_MODULE_BACKUP, /* Slave 3 (i2c address 0x4b) */
+ TWL4030_MODULE_INT,
+
+ TWL4030_MODULE_PM_MASTER,
+ TWL4030_MODULE_PM_RECEIVER,
+ TWL4030_MODULE_RTC,
+ TWL4030_MODULE_SECURED_REG,
+ TWL4030_MODULE_LAST,
+};

+/* Similar functionalities implemented in TWL4030/6030 */
#define TWL_MODULE_USB TWL4030_MODULE_USB
#define TWL_MODULE_PIH TWL4030_MODULE_PIH
#define TWL_MODULE_MAIN_CHARGE TWL4030_MODULE_MAIN_CHARGE
@@ -79,6 +79,7 @@
#define TWL_MODULE_PM_RECEIVER TWL4030_MODULE_PM_RECEIVER
#define TWL_MODULE_RTC TWL4030_MODULE_RTC
#define TWL_MODULE_PWM TWL4030_MODULE_PWM0
+#define TWL_MODULE_LED TWL4030_MODULE_LED

#define TWL6030_MODULE_ID0 0x0D
#define TWL6030_MODULE_ID1 0x0E
--
1.8.0

2012-11-13 08:29:38

by Peter Ujfalusi

[permalink] [raw]
Subject: [PATCH 04/13] MFD/rtc/gpio: twl: No need to allocate bigger buffer for write

Since the twl-core has been converted to use regmap it is no longer needed
to allocate bigger buffer for data when writing to twl.

CC: Grant Likely <[email protected]>
CC: Linus Walleij <[email protected]>
CC: Alessandro Zummo <[email protected]>
Signed-off-by: Peter Ujfalusi <[email protected]>
---
drivers/gpio/gpio-twl4030.c | 12 ++++++------
drivers/mfd/twl-core.c | 9 ++-------
drivers/mfd/twl4030-irq.c | 6 +++---
drivers/mfd/twl6030-irq.c | 4 ++--
drivers/rtc/rtc-twl.c | 32 ++++++++++++++++----------------
5 files changed, 29 insertions(+), 34 deletions(-)

diff --git a/drivers/gpio/gpio-twl4030.c b/drivers/gpio/gpio-twl4030.c
index c5f8ca2..88829c3 100644
--- a/drivers/gpio/gpio-twl4030.c
+++ b/drivers/gpio/gpio-twl4030.c
@@ -354,13 +354,13 @@ static struct gpio_chip twl_gpiochip = {

static int __devinit gpio_twl4030_pulls(u32 ups, u32 downs)
{
- u8 message[6];
+ u8 message[5];
unsigned i, gpio_bit;

/* For most pins, a pulldown was enabled by default.
* We should have data that's specific to this board.
*/
- for (gpio_bit = 1, i = 1; i < 6; i++) {
+ for (gpio_bit = 1, i = 0; i < 5; i++) {
u8 bit_mask;
unsigned j;

@@ -379,16 +379,16 @@ static int __devinit gpio_twl4030_pulls(u32 ups, u32 downs)

static int __devinit gpio_twl4030_debounce(u32 debounce, u8 mmc_cd)
{
- u8 message[4];
+ u8 message[3];

/* 30 msec of debouncing is always used for MMC card detect,
* and is optional for everything else.
*/
- message[1] = (debounce & 0xff) | (mmc_cd & 0x03);
+ message[0] = (debounce & 0xff) | (mmc_cd & 0x03);
debounce >>= 8;
- message[2] = (debounce & 0xff);
+ message[1] = (debounce & 0xff);
debounce >>= 8;
- message[3] = (debounce & 0x03);
+ message[2] = (debounce & 0x03);

return twl_i2c_write(TWL4030_MODULE_GPIO, message,
REG_GPIO_DEBEN1, 3);
diff --git a/drivers/mfd/twl-core.c b/drivers/mfd/twl-core.c
index 5043f505a..a55ab15 100644
--- a/drivers/mfd/twl-core.c
+++ b/drivers/mfd/twl-core.c
@@ -344,7 +344,7 @@ int twl_i2c_write(u8 mod_no, u8 *value, u8 reg, unsigned num_bytes)
twl = &twl_modules[sid];

ret = regmap_bulk_write(twl->regmap, twl_map[mod_no].base + reg,
- &value[1], num_bytes);
+ value, num_bytes);

if (ret)
pr_err("%s: Write failed (mod %d, reg 0x%02x count %d)\n",
@@ -406,12 +406,7 @@ EXPORT_SYMBOL(twl_i2c_read);
*/
int twl_i2c_write_u8(u8 mod_no, u8 value, u8 reg)
{
-
- /* 2 bytes offset 1 contains the data offset 0 is used by i2c_write */
- u8 temp_buffer[2] = { 0 };
- /* offset 1 contains the data */
- temp_buffer[1] = value;
- return twl_i2c_write(mod_no, temp_buffer, reg, 1);
+ return twl_i2c_write(mod_no, &value, reg, 1);
}
EXPORT_SYMBOL(twl_i2c_write_u8);

diff --git a/drivers/mfd/twl4030-irq.c b/drivers/mfd/twl4030-irq.c
index ad733d7..e900402 100644
--- a/drivers/mfd/twl4030-irq.c
+++ b/drivers/mfd/twl4030-irq.c
@@ -501,7 +501,7 @@ static void twl4030_sih_bus_sync_unlock(struct irq_data *data)
} imr;

/* byte[0] gets overwritten as we write ... */
- imr.word = cpu_to_le32(agent->imr << 8);
+ imr.word = cpu_to_le32(agent->imr);
agent->imr_change_pending = false;

/* write the whole mask ... simpler than subsetting it */
@@ -526,7 +526,7 @@ static void twl4030_sih_bus_sync_unlock(struct irq_data *data)
* any processor on the other IRQ line, EDR registers are
* shared.
*/
- status = twl_i2c_read(sih->module, bytes + 1,
+ status = twl_i2c_read(sih->module, bytes,
sih->edr_offset, sih->bytes_edr);
if (status) {
pr_err("twl4030: %s, %s --> %d\n", __func__,
@@ -538,7 +538,7 @@ static void twl4030_sih_bus_sync_unlock(struct irq_data *data)
while (edge_change) {
int i = fls(edge_change) - 1;
struct irq_data *idata;
- int byte = 1 + (i >> 2);
+ int byte = i >> 2;
int off = (i & 0x3) * 2;
unsigned int type;

diff --git a/drivers/mfd/twl6030-irq.c b/drivers/mfd/twl6030-irq.c
index b76902f..277a8db 100644
--- a/drivers/mfd/twl6030-irq.c
+++ b/drivers/mfd/twl6030-irq.c
@@ -355,7 +355,7 @@ int twl6030_init_irq(struct device *dev, int irq_num)
static struct irq_chip twl6030_irq_chip;
int status = 0;
int i;
- u8 mask[4];
+ u8 mask[3];

nr_irqs = TWL6030_NR_IRQS;

@@ -370,9 +370,9 @@ int twl6030_init_irq(struct device *dev, int irq_num)

irq_end = irq_base + nr_irqs;

+ mask[0] = 0xFF;
mask[1] = 0xFF;
mask[2] = 0xFF;
- mask[3] = 0xFF;

/* mask all int lines */
twl_i2c_write(TWL_MODULE_PIH, &mask[0], REG_INT_MSK_LINE_A, 3);
diff --git a/drivers/rtc/rtc-twl.c b/drivers/rtc/rtc-twl.c
index 9277d94..8b7464c 100644
--- a/drivers/rtc/rtc-twl.c
+++ b/drivers/rtc/rtc-twl.c
@@ -233,7 +233,7 @@ static int twl_rtc_alarm_irq_enable(struct device *dev, unsigned enabled)
*/
static int twl_rtc_read_time(struct device *dev, struct rtc_time *tm)
{
- unsigned char rtc_data[ALL_TIME_REGS + 1];
+ unsigned char rtc_data[ALL_TIME_REGS];
int ret;
u8 save_control;
u8 rtc_control;
@@ -300,15 +300,15 @@ static int twl_rtc_read_time(struct device *dev, struct rtc_time *tm)
static int twl_rtc_set_time(struct device *dev, struct rtc_time *tm)
{
unsigned char save_control;
- unsigned char rtc_data[ALL_TIME_REGS + 1];
+ unsigned char rtc_data[ALL_TIME_REGS];
int ret;

- rtc_data[1] = bin2bcd(tm->tm_sec);
- rtc_data[2] = bin2bcd(tm->tm_min);
- rtc_data[3] = bin2bcd(tm->tm_hour);
- rtc_data[4] = bin2bcd(tm->tm_mday);
- rtc_data[5] = bin2bcd(tm->tm_mon + 1);
- rtc_data[6] = bin2bcd(tm->tm_year - 100);
+ rtc_data[0] = bin2bcd(tm->tm_sec);
+ rtc_data[1] = bin2bcd(tm->tm_min);
+ rtc_data[2] = bin2bcd(tm->tm_hour);
+ rtc_data[3] = bin2bcd(tm->tm_mday);
+ rtc_data[4] = bin2bcd(tm->tm_mon + 1);
+ rtc_data[5] = bin2bcd(tm->tm_year - 100);

/* Stop RTC while updating the TC registers */
ret = twl_rtc_read_u8(&save_control, REG_RTC_CTRL_REG);
@@ -341,7 +341,7 @@ out:
*/
static int twl_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm)
{
- unsigned char rtc_data[ALL_TIME_REGS + 1];
+ unsigned char rtc_data[ALL_TIME_REGS];
int ret;

ret = twl_i2c_read(TWL_MODULE_RTC, rtc_data,
@@ -368,19 +368,19 @@ static int twl_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm)

static int twl_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm)
{
- unsigned char alarm_data[ALL_TIME_REGS + 1];
+ unsigned char alarm_data[ALL_TIME_REGS];
int ret;

ret = twl_rtc_alarm_irq_enable(dev, 0);
if (ret)
goto out;

- alarm_data[1] = bin2bcd(alm->time.tm_sec);
- alarm_data[2] = bin2bcd(alm->time.tm_min);
- alarm_data[3] = bin2bcd(alm->time.tm_hour);
- alarm_data[4] = bin2bcd(alm->time.tm_mday);
- alarm_data[5] = bin2bcd(alm->time.tm_mon + 1);
- alarm_data[6] = bin2bcd(alm->time.tm_year - 100);
+ alarm_data[0] = bin2bcd(alm->time.tm_sec);
+ alarm_data[1] = bin2bcd(alm->time.tm_min);
+ alarm_data[2] = bin2bcd(alm->time.tm_hour);
+ alarm_data[3] = bin2bcd(alm->time.tm_mday);
+ alarm_data[4] = bin2bcd(alm->time.tm_mon + 1);
+ alarm_data[5] = bin2bcd(alm->time.tm_year - 100);

/* update all the alarm registers in one shot */
ret = twl_i2c_write(TWL_MODULE_RTC, alarm_data,
--
1.8.0

2012-11-13 08:30:15

by Peter Ujfalusi

[permalink] [raw]
Subject: [PATCH 13/13] mfd: twl-core: Change TWL4030_MODULE_* ids to TWL_MODULE_*

To facilitate upcoming cleanup in twl stack.
No functional changes.

Signed-off-by: Peter Ujfalusi <[email protected]>
---
drivers/mfd/twl-core.c | 14 ++++++--------
1 file changed, 6 insertions(+), 8 deletions(-)

diff --git a/drivers/mfd/twl-core.c b/drivers/mfd/twl-core.c
index f857097..43c7b4c 100644
--- a/drivers/mfd/twl-core.c
+++ b/drivers/mfd/twl-core.c
@@ -1077,8 +1077,8 @@ static inline int __init protect_pm_master(void)
{
int e = 0;

- e = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, 0,
- TWL4030_PM_MASTER_PROTECT_KEY);
+ e = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, 0,
+ TWL4030_PM_MASTER_PROTECT_KEY);
return e;
}

@@ -1086,12 +1086,10 @@ static inline int __init unprotect_pm_master(void)
{
int e = 0;

- e |= twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER,
- TWL4030_PM_MASTER_KEY_CFG1,
- TWL4030_PM_MASTER_PROTECT_KEY);
- e |= twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER,
- TWL4030_PM_MASTER_KEY_CFG2,
- TWL4030_PM_MASTER_PROTECT_KEY);
+ e |= twl_i2c_write_u8(TWL_MODULE_PM_MASTER, TWL4030_PM_MASTER_KEY_CFG1,
+ TWL4030_PM_MASTER_PROTECT_KEY);
+ e |= twl_i2c_write_u8(TWL_MODULE_PM_MASTER, TWL4030_PM_MASTER_KEY_CFG2,
+ TWL4030_PM_MASTER_PROTECT_KEY);

return e;
}
--
1.8.0

2012-11-13 08:31:14

by Peter Ujfalusi

[permalink] [raw]
Subject: [PATCH 12/13] mfd: twl4030-irq: Change TWL4030_MODULE_* ids to TWL_MODULE_*

To facilitate upcoming cleanup in twl stack.
No functional changes.

Signed-off-by: Peter Ujfalusi <[email protected]>
---
drivers/mfd/twl4030-irq.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/mfd/twl4030-irq.c b/drivers/mfd/twl4030-irq.c
index e900402..518da0c 100644
--- a/drivers/mfd/twl4030-irq.c
+++ b/drivers/mfd/twl4030-irq.c
@@ -295,8 +295,8 @@ static irqreturn_t handle_twl4030_pih(int irq, void *devid)
irqreturn_t ret;
u8 pih_isr;

- ret = twl_i2c_read_u8(TWL4030_MODULE_PIH, &pih_isr,
- REG_PIH_ISR_P1);
+ ret = twl_i2c_read_u8(TWL_MODULE_PIH, &pih_isr,
+ REG_PIH_ISR_P1);
if (ret) {
pr_warning("twl4030: I2C error %d reading PIH ISR\n", ret);
return IRQ_NONE;
--
1.8.0

2012-11-13 08:29:10

by Peter Ujfalusi

[permalink] [raw]
Subject: [PATCH 03/13] MFD: twl-core: Convert to use regmap for I/O

Remove the custom code to do I/O and replace it with standard regmap calls.

CC: Mark Brown <[email protected]>
Signed-off-by: Peter Ujfalusi <[email protected]>
---
drivers/mfd/twl-core.c | 147 +++++++++++++++++++++++++++----------------------
1 file changed, 80 insertions(+), 67 deletions(-)

diff --git a/drivers/mfd/twl-core.c b/drivers/mfd/twl-core.c
index 1dfd583..5043f505a 100644
--- a/drivers/mfd/twl-core.c
+++ b/drivers/mfd/twl-core.c
@@ -32,6 +32,7 @@
#include <linux/mutex.h>
#include <linux/module.h>
#include <linux/platform_device.h>
+#include <linux/regmap.h>
#include <linux/clk.h>
#include <linux/err.h>
#include <linux/device.h>
@@ -171,13 +172,7 @@ EXPORT_SYMBOL(twl_rev);
/* Structure for each TWL4030/TWL6030 Slave */
struct twl_client {
struct i2c_client *client;
- u8 address;
-
- /* max numb of i2c_msg required is for read =2 */
- struct i2c_msg xfer_msg[2];
-
- /* To lock access to xfer_msg */
- struct mutex xfer_lock;
+ struct regmap *regmap;
};

static struct twl_client twl_modules[TWL_NUM_SLAVES];
@@ -225,6 +220,33 @@ static struct twl_mapping twl4030_map[TWL4030_MODULE_LAST + 1] = {
{ 3, TWL4030_BASEADD_SECURED_REG },
};

+static struct regmap_config twl4030_regmap_config[4] = {
+ {
+ /* Address 0x48 */
+ .reg_bits = 8,
+ .val_bits = 8,
+ .max_register = 0xff,
+ },
+ {
+ /* Address 0x49 */
+ .reg_bits = 8,
+ .val_bits = 8,
+ .max_register = 0xff,
+ },
+ {
+ /* Address 0x4a */
+ .reg_bits = 8,
+ .val_bits = 8,
+ .max_register = 0xff,
+ },
+ {
+ /* Address 0x4b */
+ .reg_bits = 8,
+ .val_bits = 8,
+ .max_register = 0xff,
+ },
+};
+
static struct twl_mapping twl6030_map[] = {
/*
* NOTE: don't change this table without updating the
@@ -262,6 +284,27 @@ static struct twl_mapping twl6030_map[] = {
{ SUB_CHIP_ID1, TWL6025_BASEADD_CHARGER },
};

+static struct regmap_config twl6030_regmap_config[3] = {
+ {
+ /* Address 0x48 */
+ .reg_bits = 8,
+ .val_bits = 8,
+ .max_register = 0xff,
+ },
+ {
+ /* Address 0x49 */
+ .reg_bits = 8,
+ .val_bits = 8,
+ .max_register = 0xff,
+ },
+ {
+ /* Address 0x4a */
+ .reg_bits = 8,
+ .val_bits = 8,
+ .max_register = 0xff,
+ },
+};
+
/*----------------------------------------------------------------------*/

/* Exported Functions */
@@ -283,7 +326,6 @@ int twl_i2c_write(u8 mod_no, u8 *value, u8 reg, unsigned num_bytes)
int ret;
int sid;
struct twl_client *twl;
- struct i2c_msg *msg;

if (unlikely(mod_no > TWL_MODULE_LAST)) {
pr_err("%s: invalid module number %d\n", DRIVER_NAME, mod_no);
@@ -301,32 +343,14 @@ int twl_i2c_write(u8 mod_no, u8 *value, u8 reg, unsigned num_bytes)
}
twl = &twl_modules[sid];

- mutex_lock(&twl->xfer_lock);
- /*
- * [MSG1]: fill the register address data
- * fill the data Tx buffer
- */
- msg = &twl->xfer_msg[0];
- msg->addr = twl->address;
- msg->len = num_bytes + 1;
- msg->flags = 0;
- msg->buf = value;
- /* over write the first byte of buffer with the register address */
- *value = twl_map[mod_no].base + reg;
- ret = i2c_transfer(twl->client->adapter, twl->xfer_msg, 1);
- mutex_unlock(&twl->xfer_lock);
-
- /* i2c_transfer returns number of messages transferred */
- if (ret != 1) {
- pr_err("%s: i2c_write failed to transfer all messages\n",
- DRIVER_NAME);
- if (ret < 0)
- return ret;
- else
- return -EIO;
- } else {
- return 0;
- }
+ ret = regmap_bulk_write(twl->regmap, twl_map[mod_no].base + reg,
+ &value[1], num_bytes);
+
+ if (ret)
+ pr_err("%s: Write failed (mod %d, reg 0x%02x count %d)\n",
+ DRIVER_NAME, mod_no, reg, num_bytes);
+
+ return ret;
}
EXPORT_SYMBOL(twl_i2c_write);

@@ -342,10 +366,8 @@ EXPORT_SYMBOL(twl_i2c_write);
int twl_i2c_read(u8 mod_no, u8 *value, u8 reg, unsigned num_bytes)
{
int ret;
- u8 val;
int sid;
struct twl_client *twl;
- struct i2c_msg *msg;

if (unlikely(mod_no > TWL_MODULE_LAST)) {
pr_err("%s: invalid module number %d\n", DRIVER_NAME, mod_no);
@@ -363,34 +385,14 @@ int twl_i2c_read(u8 mod_no, u8 *value, u8 reg, unsigned num_bytes)
}
twl = &twl_modules[sid];

- mutex_lock(&twl->xfer_lock);
- /* [MSG1] fill the register address data */
- msg = &twl->xfer_msg[0];
- msg->addr = twl->address;
- msg->len = 1;
- msg->flags = 0; /* Read the register value */
- val = twl_map[mod_no].base + reg;
- msg->buf = &val;
- /* [MSG2] fill the data rx buffer */
- msg = &twl->xfer_msg[1];
- msg->addr = twl->address;
- msg->flags = I2C_M_RD; /* Read the register value */
- msg->len = num_bytes; /* only n bytes */
- msg->buf = value;
- ret = i2c_transfer(twl->client->adapter, twl->xfer_msg, 2);
- mutex_unlock(&twl->xfer_lock);
-
- /* i2c_transfer returns number of messages transferred */
- if (ret != 2) {
- pr_err("%s: i2c_read failed to transfer all messages\n",
- DRIVER_NAME);
- if (ret < 0)
- return ret;
- else
- return -EIO;
- } else {
- return 0;
- }
+ ret = regmap_bulk_read(twl->regmap, twl_map[mod_no].base + reg,
+ value, num_bytes);
+
+ if (ret)
+ pr_err("%s: Read failed (mod %d, reg 0x%02x count %d)\n",
+ DRIVER_NAME, mod_no, reg, num_bytes);
+
+ return ret;
}
EXPORT_SYMBOL(twl_i2c_read);

@@ -1184,6 +1186,7 @@ twl_probe(struct i2c_client *client, const struct i2c_device_id *id)
struct twl4030_platform_data *pdata = client->dev.platform_data;
struct device_node *node = client->dev.of_node;
struct platform_device *pdev;
+ struct regmap_config *twl_regmap_config;
int irq_base = 0;
int status;
unsigned i, num_slaves;
@@ -1237,22 +1240,23 @@ twl_probe(struct i2c_client *client, const struct i2c_device_id *id)
if ((id->driver_data) & TWL6030_CLASS) {
twl_id = TWL6030_CLASS_ID;
twl_map = &twl6030_map[0];
+ twl_regmap_config = twl6030_regmap_config;
num_slaves = TWL_NUM_SLAVES - 1;
} else {
twl_id = TWL4030_CLASS_ID;
twl_map = &twl4030_map[0];
+ twl_regmap_config = twl4030_regmap_config;
num_slaves = TWL_NUM_SLAVES;
}

for (i = 0; i < num_slaves; i++) {
struct twl_client *twl = &twl_modules[i];

- twl->address = client->addr + i;
if (i == 0) {
twl->client = client;
} else {
twl->client = i2c_new_dummy(client->adapter,
- twl->address);
+ client->addr + i);
if (!twl->client) {
dev_err(&client->dev,
"can't attach client %d\n", i);
@@ -1260,7 +1264,16 @@ twl_probe(struct i2c_client *client, const struct i2c_device_id *id)
goto fail;
}
}
- mutex_init(&twl->xfer_lock);
+
+ twl->regmap = devm_regmap_init_i2c(twl->client,
+ &twl_regmap_config[i]);
+ if (IS_ERR(twl->regmap)) {
+ status = PTR_ERR(twl->regmap);
+ dev_err(&client->dev,
+ "Failed to allocate regmap %d, err: %d\n", i,
+ status);
+ goto fail;
+ }
}

inuse = true;
--
1.8.0

2012-11-13 08:31:40

by Peter Ujfalusi

[permalink] [raw]
Subject: [PATCH 10/13] mfd: twl4030-madc: Change TWL4030_MODULE_* ids to TWL_MODULE_*

To facilitate upcoming cleanup in twl stack.
No functional changes.

Signed-off-by: Peter Ujfalusi <[email protected]>
---
drivers/mfd/twl4030-madc.c | 14 +++++++-------
1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/drivers/mfd/twl4030-madc.c b/drivers/mfd/twl4030-madc.c
index 456ecb5..2baabaa 100644
--- a/drivers/mfd/twl4030-madc.c
+++ b/drivers/mfd/twl4030-madc.c
@@ -173,7 +173,7 @@ static int twl4030battery_temperature(int raw_volt)

volt = (raw_volt * TEMP_STEP_SIZE) / TEMP_PSR_R;
/* Getting and calculating the supply current in micro ampers */
- ret = twl_i2c_read_u8(TWL4030_MODULE_MAIN_CHARGE, &val,
+ ret = twl_i2c_read_u8(TWL_MODULE_MAIN_CHARGE, &val,
REG_BCICTL2);
if (ret < 0)
return ret;
@@ -196,7 +196,7 @@ static int twl4030battery_current(int raw_volt)
int ret;
u8 val;

- ret = twl_i2c_read_u8(TWL4030_MODULE_MAIN_CHARGE, &val,
+ ret = twl_i2c_read_u8(TWL_MODULE_MAIN_CHARGE, &val,
TWL4030_BCI_BCICTL1);
if (ret)
return ret;
@@ -635,7 +635,7 @@ static int twl4030_madc_set_current_generator(struct twl4030_madc_data *madc,
int ret;
u8 regval;

- ret = twl_i2c_read_u8(TWL4030_MODULE_MAIN_CHARGE,
+ ret = twl_i2c_read_u8(TWL_MODULE_MAIN_CHARGE,
&regval, TWL4030_BCI_BCICTL1);
if (ret) {
dev_err(madc->dev, "unable to read BCICTL1 reg 0x%X",
@@ -646,7 +646,7 @@ static int twl4030_madc_set_current_generator(struct twl4030_madc_data *madc,
regval |= chan ? TWL4030_BCI_ITHEN : TWL4030_BCI_TYPEN;
else
regval &= chan ? ~TWL4030_BCI_ITHEN : ~TWL4030_BCI_TYPEN;
- ret = twl_i2c_write_u8(TWL4030_MODULE_MAIN_CHARGE,
+ ret = twl_i2c_write_u8(TWL_MODULE_MAIN_CHARGE,
regval, TWL4030_BCI_BCICTL1);
if (ret) {
dev_err(madc->dev, "unable to write BCICTL1 reg 0x%X\n",
@@ -668,7 +668,7 @@ static int twl4030_madc_set_power(struct twl4030_madc_data *madc, int on)
u8 regval;
int ret;

- ret = twl_i2c_read_u8(TWL4030_MODULE_MAIN_CHARGE,
+ ret = twl_i2c_read_u8(TWL_MODULE_MAIN_CHARGE,
&regval, TWL4030_MADC_CTRL1);
if (ret) {
dev_err(madc->dev, "unable to read madc ctrl1 reg 0x%X\n",
@@ -725,7 +725,7 @@ static int __devinit twl4030_madc_probe(struct platform_device *pdev)
if (ret < 0)
goto err_current_generator;

- ret = twl_i2c_read_u8(TWL4030_MODULE_MAIN_CHARGE,
+ ret = twl_i2c_read_u8(TWL_MODULE_MAIN_CHARGE,
&regval, TWL4030_BCI_BCICTL1);
if (ret) {
dev_err(&pdev->dev, "unable to read reg BCI CTL1 0x%X\n",
@@ -733,7 +733,7 @@ static int __devinit twl4030_madc_probe(struct platform_device *pdev)
goto err_i2c;
}
regval |= TWL4030_BCI_MESBAT;
- ret = twl_i2c_write_u8(TWL4030_MODULE_MAIN_CHARGE,
+ ret = twl_i2c_write_u8(TWL_MODULE_MAIN_CHARGE,
regval, TWL4030_BCI_BCICTL1);
if (ret) {
dev_err(&pdev->dev, "unable to write reg BCI Ctl1 0x%X\n",
--
1.8.0

2012-11-13 08:32:04

by Peter Ujfalusi

[permalink] [raw]
Subject: [PATCH 09/13] MFD: twl-core: re-group the twl_mapping table for easier reading

Group the twl_mapping table in 5 lines chunks so it is more easier to find
the row we are looking for (if we need to).

Signed-off-by: Peter Ujfalusi <[email protected]>
---
drivers/mfd/twl-core.c | 9 +++++----
1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/drivers/mfd/twl-core.c b/drivers/mfd/twl-core.c
index bb33b52..f857097 100644
--- a/drivers/mfd/twl-core.c
+++ b/drivers/mfd/twl-core.c
@@ -189,28 +189,29 @@ static struct twl_mapping twl4030_map[] = {
*/

{ 0, TWL4030_BASEADD_USB },
-
{ 1, TWL4030_BASEADD_AUDIO_VOICE },
{ 1, TWL4030_BASEADD_GPIO },
{ 1, TWL4030_BASEADD_INTBR },
{ 1, TWL4030_BASEADD_PIH },
- { 1, TWL4030_BASEADD_TEST },

+ { 1, TWL4030_BASEADD_TEST },
{ 2, TWL4030_BASEADD_KEYPAD },
{ 2, TWL4030_BASEADD_MADC },
{ 2, TWL4030_BASEADD_INTERRUPTS },
{ 2, TWL4030_BASEADD_LED },
+
{ 2, TWL4030_BASEADD_MAIN_CHARGE },
{ 2, TWL4030_BASEADD_PRECHARGE },
{ 2, TWL4030_BASEADD_PWM0 },
{ 2, TWL4030_BASEADD_PWM1 },
{ 2, TWL4030_BASEADD_PWMA },
+
{ 2, TWL4030_BASEADD_PWMB },
{ 2, TWL5031_BASEADD_ACCESSORY },
{ 2, TWL5031_BASEADD_INTERRUPTS },
-
{ 3, TWL4030_BASEADD_BACKUP },
{ 3, TWL4030_BASEADD_INT },
+
{ 3, TWL4030_BASEADD_PM_MASTER },
{ 3, TWL4030_BASEADD_PM_RECEIVER },
{ 3, TWL4030_BASEADD_RTC },
@@ -273,9 +274,9 @@ static struct twl_mapping twl6030_map[] = {
{ SUB_CHIP_ID2, TWL6030_BASEADD_RSV },
{ SUB_CHIP_ID2, TWL6030_BASEADD_RSV },
{ SUB_CHIP_ID2, TWL6030_BASEADD_RSV },
+
{ SUB_CHIP_ID0, TWL6030_BASEADD_PM_MASTER },
{ SUB_CHIP_ID0, TWL6030_BASEADD_PM_SLAVE_MISC },
-
{ SUB_CHIP_ID0, TWL6030_BASEADD_RTC },
{ SUB_CHIP_ID0, TWL6030_BASEADD_MEM },
{ SUB_CHIP_ID1, TWL6025_BASEADD_CHARGER },
--
1.8.0

2012-11-13 08:29:08

by Peter Ujfalusi

[permalink] [raw]
Subject: [PATCH 05/13] MFD: twl-core: Clean up and correct child registration

Make the twl child registration calls a bit more uniform by always using the
SUB_CHIP_ID* define instead of the mixed use of the define and magic number.

At the same time correct the following devices so they are registered for the
correct parent device (i2c slave):
twl4030_wdt is accessible on 0x4b address and not 0x48
twl4030_pwrbutton is accessible on 0x4b address and not 0x49
twl4030-audio is on 0x49 all the time

Signed-off-by: Peter Ujfalusi <[email protected]>
---
drivers/mfd/twl-core.c | 27 ++++++++++++---------------
1 file changed, 12 insertions(+), 15 deletions(-)

diff --git a/drivers/mfd/twl-core.c b/drivers/mfd/twl-core.c
index a55ab15..d666c9d 100644
--- a/drivers/mfd/twl-core.c
+++ b/drivers/mfd/twl-core.c
@@ -645,7 +645,7 @@ add_children(struct twl4030_platform_data *pdata, unsigned irq_base,

if (IS_ENABLED(CONFIG_TWL4030_MADC) && pdata->madc &&
twl_class_is_4030()) {
- child = add_child(2, "twl4030_madc",
+ child = add_child(SUB_CHIP_ID2, "twl4030_madc",
pdata->madc, sizeof(*pdata->madc),
true, irq_base + MADC_INTR_OFFSET, 0);
if (IS_ERR(child))
@@ -661,8 +661,7 @@ add_children(struct twl4030_platform_data *pdata, unsigned irq_base,
* HW security concerns, and "least privilege".
*/
sub_chip_id = twl_map[TWL_MODULE_RTC].sid;
- child = add_child(sub_chip_id, "twl_rtc",
- NULL, 0,
+ child = add_child(sub_chip_id, "twl_rtc", NULL, 0,
true, irq_base + RTC_INTR_OFFSET, 0);
if (IS_ERR(child))
return PTR_ERR(child);
@@ -728,9 +727,8 @@ add_children(struct twl4030_platform_data *pdata, unsigned irq_base,

}

- child = add_child(0, "twl4030_usb",
- pdata->usb, sizeof(*pdata->usb),
- true,
+ child = add_child(SUB_CHIP_ID0, "twl4030_usb",
+ pdata->usb, sizeof(*pdata->usb), true,
/* irq0 = USB_PRES, irq1 = USB */
irq_base + USB_PRES_INTR_OFFSET,
irq_base + USB_INTR_OFFSET);
@@ -778,9 +776,8 @@ add_children(struct twl4030_platform_data *pdata, unsigned irq_base,

pdata->usb->features = features;

- child = add_child(0, "twl6030_usb",
- pdata->usb, sizeof(*pdata->usb),
- true,
+ child = add_child(SUB_CHIP_ID0, "twl6030_usb",
+ pdata->usb, sizeof(*pdata->usb), true,
/* irq1 = VBUS_PRES, irq0 = USB ID */
irq_base + USBOTG_INTR_OFFSET,
irq_base + USB_PRES_INTR_OFFSET);
@@ -804,22 +801,22 @@ add_children(struct twl4030_platform_data *pdata, unsigned irq_base,
}

if (IS_ENABLED(CONFIG_TWL4030_WATCHDOG) && twl_class_is_4030()) {
- child = add_child(0, "twl4030_wdt", NULL, 0, false, 0, 0);
+ child = add_child(SUB_CHIP_ID3, "twl4030_wdt", NULL, 0,
+ false, 0, 0);
if (IS_ERR(child))
return PTR_ERR(child);
}

if (IS_ENABLED(CONFIG_INPUT_TWL4030_PWRBUTTON) && twl_class_is_4030()) {
- child = add_child(1, "twl4030_pwrbutton",
- NULL, 0, true, irq_base + 8 + 0, 0);
+ child = add_child(SUB_CHIP_ID3, "twl4030_pwrbutton", NULL, 0,
+ true, irq_base + 8 + 0, 0);
if (IS_ERR(child))
return PTR_ERR(child);
}

if (IS_ENABLED(CONFIG_MFD_TWL4030_AUDIO) && pdata->audio &&
twl_class_is_4030()) {
- sub_chip_id = twl_map[TWL_MODULE_AUDIO_VOICE].sid;
- child = add_child(sub_chip_id, "twl4030-audio",
+ child = add_child(SUB_CHIP_ID1, "twl4030-audio",
pdata->audio, sizeof(*pdata->audio),
false, 0, 0);
if (IS_ERR(child))
@@ -1059,7 +1056,7 @@ add_children(struct twl4030_platform_data *pdata, unsigned irq_base,

if (IS_ENABLED(CONFIG_CHARGER_TWL4030) && pdata->bci &&
!(features & (TPS_SUBSET | TWL5031))) {
- child = add_child(3, "twl4030_bci",
+ child = add_child(SUB_CHIP_ID3, "twl4030_bci",
pdata->bci, sizeof(*pdata->bci), false,
/* irq0 = CHG_PRES, irq1 = BCI */
irq_base + BCI_PRES_INTR_OFFSET,
--
1.8.0

2012-11-13 08:32:31

by Peter Ujfalusi

[permalink] [raw]
Subject: [PATCH 06/13] mfd: twl: Remove unused TWL_MODULE definitions

AUDIO and MADC only available on twl4030 series and the TWL_MODULE_* mapping
is not needed.

Signed-off-by: Peter Ujfalusi <[email protected]>
---
include/linux/i2c/twl.h | 2 --
1 file changed, 2 deletions(-)

diff --git a/include/linux/i2c/twl.h b/include/linux/i2c/twl.h
index 9a5e284..7278c72 100644
--- a/include/linux/i2c/twl.h
+++ b/include/linux/i2c/twl.h
@@ -73,9 +73,7 @@
#define TWL4030_MODULE_SECURED_REG 0x17

#define TWL_MODULE_USB TWL4030_MODULE_USB
-#define TWL_MODULE_AUDIO_VOICE TWL4030_MODULE_AUDIO_VOICE
#define TWL_MODULE_PIH TWL4030_MODULE_PIH
-#define TWL_MODULE_MADC TWL4030_MODULE_MADC
#define TWL_MODULE_MAIN_CHARGE TWL4030_MODULE_MAIN_CHARGE
#define TWL_MODULE_PM_MASTER TWL4030_MODULE_PM_MASTER
#define TWL_MODULE_PM_RECEIVER TWL4030_MODULE_PM_RECEIVER
--
1.8.0

2012-11-13 08:32:52

by Mark Brown

[permalink] [raw]
Subject: Re: [PATCH 03/13] MFD: twl-core: Convert to use regmap for I/O

On Tue, Nov 13, 2012 at 09:28:44AM +0100, Peter Ujfalusi wrote:
> Remove the custom code to do I/O and replace it with standard regmap calls.
>
> CC: Mark Brown <[email protected]>
> Signed-off-by: Peter Ujfalusi <[email protected]>

Reviewed-by: Mark Brown <[email protected]>


Attachments:
(No filename) (319.00 B)
signature.asc (836.00 B)
Digital signature
Download all attachments

2012-11-13 08:33:35

by Peter Ujfalusi

[permalink] [raw]
Subject: [PATCH 02/13] MFD: twl-core: Support for proper PWM drivers

The twl6030-pwm driver is going to be deleted since it was only able to
control the Charging indicator LED on the twl6030 PMIC.
The new set of drivers are going to provide support for both PWMs and PWM
driven LED outputs on TWL4030 and TWL6030 PMICs.
The twl-pwm driver will handle the PWMs (2 instance) while the twl-pwmled
driver is to control the two LED instance on TWL4030 and to charging
indicator LED (1 instance) on TWL6030.

Signed-off-by: Peter Ujfalusi <[email protected]>
---
drivers/mfd/twl-core.c | 11 +++++++++--
1 file changed, 9 insertions(+), 2 deletions(-)

diff --git a/drivers/mfd/twl-core.c b/drivers/mfd/twl-core.c
index d7577cb..1dfd583 100644
--- a/drivers/mfd/twl-core.c
+++ b/drivers/mfd/twl-core.c
@@ -671,8 +671,15 @@ add_children(struct twl4030_platform_data *pdata, unsigned irq_base,
return PTR_ERR(child);
}

- if (IS_ENABLED(CONFIG_PWM_TWL6030) && twl_class_is_6030()) {
- child = add_child(SUB_CHIP_ID1, "twl6030-pwm", NULL, 0,
+ if (IS_ENABLED(CONFIG_PWM_TWL)) {
+ child = add_child(SUB_CHIP_ID1, "twl-pwm", NULL, 0,
+ false, 0, 0);
+ if (IS_ERR(child))
+ return PTR_ERR(child);
+ }
+
+ if (IS_ENABLED(CONFIG_PWM_TWL_LED)) {
+ child = add_child(SUB_CHIP_ID1, "twl-pwmled", NULL, 0,
false, 0, 0);
if (IS_ERR(child))
return PTR_ERR(child);
--
1.8.0

2012-11-15 14:08:15

by Linus Walleij

[permalink] [raw]
Subject: Re: [PATCH 04/13] MFD/rtc/gpio: twl: No need to allocate bigger buffer for write

On Tue, Nov 13, 2012 at 9:28 AM, Peter Ujfalusi <[email protected]> wrote:

> Since the twl-core has been converted to use regmap it is no longer needed
> to allocate bigger buffer for data when writing to twl.
>
> CC: Grant Likely <[email protected]>
> CC: Linus Walleij <[email protected]>
> CC: Alessandro Zummo <[email protected]>
> Signed-off-by: Peter Ujfalusi <[email protected]>

Acked-by: Linus Walleij <[email protected]>

I guess this will go through the MFD tree.

Yours,
Linus Walleij

2012-11-16 14:44:24

by Tero Kristo

[permalink] [raw]
Subject: Re: [PATCH 00/13] MFD: twl drivers: Convert to regmap IO and cleanups

Hi Peter / Samuel,

I just tested this set on omap3beagle + omap4460 panda boards and both
seem to work fine. Did a boot + simple PM test for both to see that
regulator control (which is using the I2C related stuff you have
changed) works. Also, looking at the code everything seems to be okay to
me, thus for whole set:

Acked-by: Tero Kristo <[email protected]>

On Tue, 2012-11-13 at 09:28 +0100, Peter Ujfalusi wrote:
> Hello,
>
> This series converts the twl-core to use regmap for IO towards the chip.
> With the conversion to regmap IO we no longer need to allocate bigger buffer for
> writes.
> I have appended patches to this series to make some cleanups which will help in
> the future to further clean up the twl stack.
>
> The series depends on a regression fix patch for the twl-core:
> https://patchwork.kernel.org/patch/1679421/
>
> Regards,
> Peter
> ---
> Peter Ujfalusi (13):
> MFD: twl-core: Register twl4030-madc child only for twl4030 class
> MFD: twl-core: Support for proper PWM drivers
> MFD: twl-core: Convert to use regmap for I/O
> MFD/rtc/gpio: twl: No need to allocate bigger buffer for write
> MFD: twl-core: Clean up and correct child registration
> mfd: twl: Remove unused TWL_MODULE definitions
> mfd: twl: Convert module id definitions to enums
> mfd: twl: Use decimal numbers for TWL6030_MODULE_IDs
> MFD: twl-core: re-group the twl_mapping table for easier reading
> mfd: twl4030-madc: Change TWL4030_MODULE_* ids to TWL_MODULE_*
> mfd: twl4030-power: Change TWL4030_MODULE_* ids to TWL_MODULE_*
> mfd: twl4030-irq: Change TWL4030_MODULE_* ids to TWL_MODULE_*
> mfd: twl-core: Change TWL4030_MODULE_* ids to TWL_MODULE_*
>
> drivers/gpio/gpio-twl4030.c | 12 +--
> drivers/mfd/twl-core.c | 227 +++++++++++++++++++++++---------------------
> drivers/mfd/twl4030-irq.c | 10 +-
> drivers/mfd/twl4030-madc.c | 14 +--
> drivers/mfd/twl4030-power.c | 124 ++++++++++--------------
> drivers/mfd/twl6030-irq.c | 4 +-
> drivers/rtc/rtc-twl.c | 32 +++----
> include/linux/i2c/twl.h | 73 +++++++-------
> 8 files changed, 241 insertions(+), 255 deletions(-)
>

2012-11-21 14:54:13

by Samuel Ortiz

[permalink] [raw]
Subject: Re: [PATCH 00/13] MFD: twl drivers: Convert to regmap IO and cleanups

Hi Peter,

On Tue, Nov 13, 2012 at 09:28:41AM +0100, Peter Ujfalusi wrote:
> Hello,
>
> This series converts the twl-core to use regmap for IO towards the chip.
> With the conversion to regmap IO we no longer need to allocate bigger buffer for
> writes.
> I have appended patches to this series to make some cleanups which will help in
> the future to further clean up the twl stack.
>
> The series depends on a regression fix patch for the twl-core:
> https://patchwork.kernel.org/patch/1679421/
>
> Regards,
> Peter
> ---
> Peter Ujfalusi (13):
> MFD: twl-core: Register twl4030-madc child only for twl4030 class
> MFD: twl-core: Support for proper PWM drivers
> MFD: twl-core: Convert to use regmap for I/O
> MFD/rtc/gpio: twl: No need to allocate bigger buffer for write
> MFD: twl-core: Clean up and correct child registration
> mfd: twl: Remove unused TWL_MODULE definitions
> mfd: twl: Convert module id definitions to enums
> mfd: twl: Use decimal numbers for TWL6030_MODULE_IDs
> MFD: twl-core: re-group the twl_mapping table for easier reading
> mfd: twl4030-madc: Change TWL4030_MODULE_* ids to TWL_MODULE_*
> mfd: twl4030-power: Change TWL4030_MODULE_* ids to TWL_MODULE_*
> mfd: twl4030-irq: Change TWL4030_MODULE_* ids to TWL_MODULE_*
> mfd: twl-core: Change TWL4030_MODULE_* ids to TWL_MODULE_*
All patches applied now, thanks.

Cheers,
Samuel.

--
Intel Open Source Technology Centre
http://oss.intel.com/