summaryrefslogtreecommitdiff
path: root/drivers/mfd
diff options
context:
space:
mode:
authorLaxman Dewangan <ldewangan@nvidia.com>2012-07-19 20:17:14 +0530
committerSimone Willett <swillett@nvidia.com>2012-07-23 10:40:26 -0700
commitb514ab80b45d2e4d8e504f798c01eb5ff47a4a0e (patch)
tree19b649fb31991770c4b759b03e3cc8c5359fd2d8 /drivers/mfd
parente6a836a6312c24e98ccb0fe059a569470b9de32d (diff)
mfd: tps80031: use regmap for register access
Use regmap for register access of device in place of direct i2c calls. This helps to have the debug FS support through regmap and also help to caching register with minimum configuration. Change-Id: I2a1285ab750639babcda40ba53001e7d1bd10a71 Signed-off-by: Laxman Dewangan <ldewangan@nvidia.com> Reviewed-on: http://git-master/r/117332 Reviewed-by: Automatic_Commit_Validation_User Reviewed-by: Bitan Biswas <bbiswas@nvidia.com> GVS: Gerrit_Virtual_Submit
Diffstat (limited to 'drivers/mfd')
-rw-r--r--drivers/mfd/tps80031.c309
1 files changed, 175 insertions, 134 deletions
diff --git a/drivers/mfd/tps80031.c b/drivers/mfd/tps80031.c
index 5b287eb12241..691c9d2ee798 100644
--- a/drivers/mfd/tps80031.c
+++ b/drivers/mfd/tps80031.c
@@ -30,6 +30,7 @@
#include <linux/gpio.h>
#include <linux/i2c.h>
#include <linux/pm.h>
+#include <linux/regmap.h>
#include <linux/mfd/core.h>
#include <linux/mfd/tps80031.h>
@@ -108,6 +109,43 @@
#define TPS80031_BBSPOR_CFG 0xE6
#define TPS80031_BBSPOR_CHG_EN 0x8
+/* Valid Address ranges */
+#define TPS80031_ID0_PMIC_SLAVE_SMPS_DVS 0x55 ... 0x5C
+
+#define TPS80031_ID1_RTC 0x00 ... 0x16
+#define TPS80031_ID1_MEMORY 0x17 ... 0x1E
+#define TPS80031_ID1_PMC_MASTER 0x1F ... 0x2D
+#define TPS80031_ID1_PMC_SLAVE_MISC 0x31 ... 0x34
+#define TPS80031_ID1_PMC_SLAVE_SMPS 0x40 ... 0x68
+#define TPS80031_ID1_PMC_SLAVE_LDO 0x80 ... 0xA7
+#define TPS80031_ID1_PMC_SLAVE_REOSURCES 0XAD ... 0xD0
+#define TPS80031_ID1_PMC_PREQ_ASSIGN 0XD7 ... 0xDF
+#define TPS80031_ID1_PMC_MISC 0xE2 ... 0xEF
+#define TPS80031_ID1_PMC_PU_PD_HZ 0xF0 ... 0xF6
+#define TPS80031_ID1_PMC_BACKUP 0xFA
+
+#define TPS80031_ID2_USB 0x00 ... 0x1A
+#define TPS80031_ID2_GPADC_CONTROL 0x2E ... 0x36
+#define TPS80031_ID2_GPADC_RESULTS 0x37 ... 0x3C
+#define TPS80031_ID2_AUXILLIARIES 0x90 ... 0x9C
+#define TPS80031_ID2_CUSTOM 0xA0 ... 0xB9
+#define TPS80031_ID2_PWM 0xBA ... 0xBE
+#define TPS80031_ID2_FUEL_GAUSE 0xC0 ... 0xCB
+#define TPS80031_ID2_INTERFACE_INTERRUPTS 0xD0 ... 0xD8
+#define TPS80031_ID2_CHARGER 0xE0 ... 0xF5
+
+#define TPS80031_ID3_TEST_LDO 0x00 ... 0x09
+#define TPS80031_ID3_TEST_SMPS 0x10 ... 0x2B
+#define TPS80031_ID3_TEST_POWER 0x30 ... 0x36
+#define TPS80031_ID3_TEST_CHARGER 0x40 ... 0x48
+#define TPS80031_ID3_TEST_AUXILIIARIES 0x50 ... 0xB1
+
+#define TPS80031_ID3_DIEID 0xC0 ... 0xC8
+#define TPS80031_ID3_TRIM_PHOENIX 0xCC ... 0xEA
+#define TPS80031_ID3_TRIM_CUSTOM 0xEC ... 0xED
+
+#define TPS80031_MAX_REGISTER 0x100
+
struct tps80031_pupd_data {
u8 reg;
u8 pullup_bit;
@@ -256,159 +294,64 @@ struct tps80031 {
u8 cont_int_en;
u8 prev_cont_stat1;
struct tps80031_client tps_clients[TPS_NUM_SLAVES];
+ struct regmap *regmap[TPS_NUM_SLAVES];
};
-static inline int __tps80031_read(struct i2c_client *client,
- int reg, uint8_t *val)
-{
- int ret;
-
- ret = i2c_smbus_read_byte_data(client, reg);
- if (ret < 0) {
- dev_err(&client->dev,
- "failed reading from addr 0x%02x, reg 0x%02x\n",
- client->addr, reg);
- return ret;
- }
-
- *val = (uint8_t)ret;
-
- return 0;
-}
-
-static inline int __tps80031_reads(struct i2c_client *client, int reg,
- int len, uint8_t *val)
-{
- int ret;
-
- ret = i2c_smbus_read_i2c_block_data(client, reg, len, val);
- if (ret < 0) {
- dev_err(&client->dev,
- "failed reading from addr 0x%02x, reg 0x%02x\n",
- client->addr, reg);
- return ret;
- }
-
- return 0;
-}
-
-static inline int __tps80031_write(struct i2c_client *client,
- int reg, uint8_t val)
-{
- int ret;
- ret = i2c_smbus_write_byte_data(client, reg, val);
- if (ret < 0) {
- dev_err(&client->dev,
- "failed writing 0x%02x to 0x%02x\n", val, reg);
- return ret;
- }
-
- return 0;
-}
-
-static inline int __tps80031_writes(struct i2c_client *client, int reg,
- int len, uint8_t *val)
-{
- int ret;
-
- ret = i2c_smbus_write_i2c_block_data(client, reg, len, val);
- if (ret < 0) {
- dev_err(&client->dev, "failed writings to 0x%02x\n", reg);
- return ret;
- }
-
- return 0;
-}
-
int tps80031_write(struct device *dev, int sid, int reg, uint8_t val)
{
struct tps80031 *tps80031 = dev_get_drvdata(dev);
- struct tps80031_client *tps = &tps80031->tps_clients[sid];
- int ret;
-
- mutex_lock(&tps->lock);
- ret = __tps80031_write(tps->client, reg, val);
- mutex_unlock(&tps->lock);
- return ret;
+ return regmap_write(tps80031->regmap[sid], reg, val);
}
EXPORT_SYMBOL_GPL(tps80031_write);
int tps80031_writes(struct device *dev, int sid, int reg, int len, uint8_t *val)
{
struct tps80031 *tps80031 = dev_get_drvdata(dev);
- struct tps80031_client *tps = &tps80031->tps_clients[sid];
- int ret;
-
- mutex_lock(&tps->lock);
- ret = __tps80031_writes(tps->client, reg, len, val);
- mutex_unlock(&tps->lock);
- return ret;
+ return regmap_bulk_write(tps80031->regmap[sid], reg, val, len);
}
EXPORT_SYMBOL_GPL(tps80031_writes);
int tps80031_read(struct device *dev, int sid, int reg, uint8_t *val)
{
struct tps80031 *tps80031 = dev_get_drvdata(dev);
- struct tps80031_client *tps = &tps80031->tps_clients[sid];
+ unsigned int ival;
+ int ret;
- return __tps80031_read(tps->client, reg, val);
+ ret = regmap_read(tps80031->regmap[sid], reg, &ival);
+ if (ret < 0) {
+ dev_err(dev, "failed reading from reg 0x%02x\n", reg);
+ return ret;
+ }
+
+ *val = ival;
+ return ret;
}
EXPORT_SYMBOL_GPL(tps80031_read);
int tps80031_reads(struct device *dev, int sid, int reg, int len, uint8_t *val)
{
struct tps80031 *tps80031 = dev_get_drvdata(dev);
- struct tps80031_client *tps = &tps80031->tps_clients[sid];
- return __tps80031_reads(tps->client, reg, len, val);
+ return regmap_bulk_read(tps80031->regmap[sid], reg, val, len);
}
EXPORT_SYMBOL_GPL(tps80031_reads);
int tps80031_set_bits(struct device *dev, int sid, int reg, uint8_t bit_mask)
{
struct tps80031 *tps80031 = dev_get_drvdata(dev);
- struct tps80031_client *tps = &tps80031->tps_clients[sid];
- uint8_t reg_val;
- int ret = 0;
-
- mutex_lock(&tps->lock);
-
- ret = __tps80031_read(tps->client, reg, &reg_val);
- if (ret)
- goto out;
- if ((reg_val & bit_mask) != bit_mask) {
- reg_val |= bit_mask;
- ret = __tps80031_write(tps->client, reg, reg_val);
- }
-out:
- mutex_unlock(&tps->lock);
- return ret;
+ return regmap_update_bits(tps80031->regmap[sid], reg,
+ bit_mask, bit_mask);
}
EXPORT_SYMBOL_GPL(tps80031_set_bits);
int tps80031_clr_bits(struct device *dev, int sid, int reg, uint8_t bit_mask)
{
struct tps80031 *tps80031 = dev_get_drvdata(dev);
- struct tps80031_client *tps = &tps80031->tps_clients[sid];
- uint8_t reg_val;
- int ret = 0;
- mutex_lock(&tps->lock);
-
- ret = __tps80031_read(tps->client, reg, &reg_val);
- if (ret)
- goto out;
-
- if (reg_val & bit_mask) {
- reg_val &= ~bit_mask;
- ret = __tps80031_write(tps->client, reg, reg_val);
- }
-out:
- mutex_unlock(&tps->lock);
- return ret;
+ return regmap_update_bits(tps80031->regmap[sid], reg, bit_mask, 0);
}
EXPORT_SYMBOL_GPL(tps80031_clr_bits);
@@ -416,23 +359,8 @@ int tps80031_update(struct device *dev, int sid, int reg, uint8_t val,
uint8_t mask)
{
struct tps80031 *tps80031 = dev_get_drvdata(dev);
- struct tps80031_client *tps = &tps80031->tps_clients[sid];
- uint8_t reg_val;
- int ret = 0;
-
- mutex_lock(&tps->lock);
-
- ret = __tps80031_read(tps->client, reg, &reg_val);
- if (ret)
- goto out;
- if ((reg_val & mask) != val) {
- reg_val = (reg_val & ~mask) | (val & mask);
- ret = __tps80031_write(tps->client, reg, reg_val);
- }
-out:
- mutex_unlock(&tps->lock);
- return ret;
+ return regmap_update_bits(tps80031->regmap[sid], reg, mask, val);
}
EXPORT_SYMBOL_GPL(tps80031_update);
@@ -446,12 +374,12 @@ int tps80031_force_update(struct device *dev, int sid, int reg, uint8_t val,
mutex_lock(&tps->lock);
- ret = __tps80031_read(tps->client, reg, &reg_val);
+ ret = tps80031_read(dev, sid, reg, &reg_val);
if (ret)
goto out;
reg_val = (reg_val & ~mask) | (val & mask);
- ret = __tps80031_write(tps->client, reg, reg_val);
+ ret = tps80031_write(dev, sid, reg, reg_val);
out:
mutex_unlock(&tps->lock);
@@ -544,7 +472,8 @@ static void tps80031_power_off(void)
if (!tps->client)
return;
dev_info(&tps->client->dev, "switching off PMU\n");
- __tps80031_write(tps->client, TPS80031_PHOENIX_DEV_ON, DEVOFF);
+ tps80031_write(&tps->client->dev, SLAVE_ID1,
+ TPS80031_PHOENIX_DEV_ON, DEVOFF);
}
static void tps80031_pupd_init(struct tps80031 *tps80031,
@@ -613,14 +542,14 @@ static int tps80031_gpio_get(struct gpio_chip *gc, unsigned offset)
uint8_t trans;
int ret;
- ret = __tps80031_read(tps->client,
+ ret = tps80031_read(&tps->client->dev, SLAVE_ID1,
pmc_ext_control_base[offset] +
EXT_CONTROL_CFG_STATE, &state);
if (ret)
return ret;
if (state != 0) {
- ret = __tps80031_read(tps->client,
+ ret = tps80031_read(&tps->client->dev, SLAVE_ID1,
pmc_ext_control_base[offset] +
EXT_CONTROL_CFG_TRANS, &trans);
if (ret)
@@ -1115,7 +1044,7 @@ static void print_regs(const char *header, struct seq_file *s,
seq_printf(s, "%s\n", header);
for (i = start_offset; i <= end_offset; ++i) {
- ret = __tps80031_read(tps->client, i, &reg_val);
+ ret = tps80031_read(&tps->client->dev, sid, i, &reg_val);
if (ret >= 0)
seq_printf(s, "Addr = 0x%02x Reg 0x%02x Value 0x%02x\n",
tps->client->addr, i, reg_val);
@@ -1189,6 +1118,109 @@ static void __init tps80031_debuginit(struct tps80031 *tpsi)
}
#endif
+static bool rd_wr_reg_id0(struct device *dev, unsigned int reg)
+{
+ switch(reg) {
+ case TPS80031_ID0_PMIC_SLAVE_SMPS_DVS:
+ return true;
+ default:
+ pr_err("non-existing reg %s() %d reg %x\n", __func__, __LINE__, reg);
+ BUG();
+ return false;
+ }
+}
+
+static bool rd_wr_reg_id1(struct device *dev, unsigned int reg)
+{
+ switch(reg) {
+ case TPS80031_ID1_RTC:
+ case TPS80031_ID1_MEMORY:
+ case TPS80031_ID1_PMC_MASTER:
+ case TPS80031_ID1_PMC_SLAVE_SMPS:
+ case TPS80031_ID1_PMC_SLAVE_MISC:
+ case TPS80031_ID1_PMC_SLAVE_LDO:
+ case TPS80031_ID1_PMC_SLAVE_REOSURCES:
+ case TPS80031_ID1_PMC_PREQ_ASSIGN:
+ case TPS80031_ID1_PMC_MISC:
+ case TPS80031_ID1_PMC_PU_PD_HZ:
+ case TPS80031_ID1_PMC_BACKUP:
+ return true;
+ default:
+ pr_err("non-existing reg %s() %d reg %x\n", __func__, __LINE__, reg);
+ BUG();
+ return false;
+ }
+}
+
+static bool rd_wr_reg_id2(struct device *dev, unsigned int reg)
+{
+ switch(reg) {
+ case TPS80031_ID2_USB:
+ case TPS80031_ID2_GPADC_CONTROL:
+ case TPS80031_ID2_GPADC_RESULTS:
+ case TPS80031_ID2_AUXILLIARIES:
+ case TPS80031_ID2_CUSTOM:
+ case TPS80031_ID2_PWM:
+ case TPS80031_ID2_FUEL_GAUSE:
+ case TPS80031_ID2_INTERFACE_INTERRUPTS:
+ case TPS80031_ID2_CHARGER:
+ return true;
+ default:
+ pr_err("non-existing reg %s() %d reg %x\n", __func__, __LINE__, reg);
+ BUG();
+ return false;
+ }
+}
+static bool rd_wr_reg_id3(struct device *dev, unsigned int reg)
+{
+ switch(reg) {
+ case TPS80031_ID3_TEST_LDO:
+ case TPS80031_ID3_TEST_SMPS:
+ case TPS80031_ID3_TEST_POWER:
+ case TPS80031_ID3_TEST_CHARGER:
+ case TPS80031_ID3_TEST_AUXILIIARIES:
+ case TPS80031_ID3_DIEID:
+ case TPS80031_ID3_TRIM_PHOENIX:
+ case TPS80031_ID3_TRIM_CUSTOM:
+ return true;
+ default:
+ pr_err("non-existing reg %s() %d reg %x\n", __func__, __LINE__, reg);
+ BUG();
+ return false;
+ }
+}
+
+static const struct regmap_config tps80031_regmap_configs[] = {
+ {
+ .reg_bits = 8,
+ .val_bits = 8,
+ .writeable_reg = rd_wr_reg_id0,
+ .readable_reg = rd_wr_reg_id0,
+ .max_register = TPS80031_MAX_REGISTER - 1,
+ },
+ {
+ .reg_bits = 8,
+ .val_bits = 8,
+ .writeable_reg = rd_wr_reg_id1,
+ .readable_reg = rd_wr_reg_id1,
+ .max_register = TPS80031_MAX_REGISTER - 1,
+ },
+ {
+ .reg_bits = 8,
+ .val_bits = 8,
+ .writeable_reg = rd_wr_reg_id2,
+ .readable_reg = rd_wr_reg_id2,
+ .max_register = TPS80031_MAX_REGISTER - 1,
+ },
+ {
+ .reg_bits = 8,
+ .val_bits = 8,
+ .writeable_reg = rd_wr_reg_id3,
+ .readable_reg = rd_wr_reg_id3,
+ .max_register = TPS80031_MAX_REGISTER - 1,
+ },
+};
+
static int __devexit tps80031_i2c_remove(struct i2c_client *client)
{
struct tps80031 *tps80031 = i2c_get_clientdata(client);
@@ -1275,6 +1307,15 @@ static int __devinit tps80031_i2c_probe(struct i2c_client *client,
}
i2c_set_clientdata(tps->client, tps80031);
mutex_init(&tps->lock);
+
+ tps80031->regmap[i] = devm_regmap_init_i2c(tps->client,
+ &tps80031_regmap_configs[i]);
+ if (IS_ERR(tps80031->regmap[i])) {
+ ret = PTR_ERR(tps80031->regmap[i]);
+ dev_err(&client->dev,
+ "regmap %d init failed, err %d\n", i, ret);
+ goto fail;
+ }
}
if (client->irq) {