diff options
author | Syed Rafiuddin <srafiuddin@nvidia.com> | 2012-04-13 15:39:05 +0530 |
---|---|---|
committer | Simone Willett <swillett@nvidia.com> | 2012-04-18 18:30:22 -0700 |
commit | 1936560a16edfe970ae286c2a7f60c445e36086a (patch) | |
tree | ff173a0ab953bff067a9ef22a9e596f41c85e068 /drivers/power | |
parent | fd5af65bc99c11f65fd400f08d67e9d2470c9d9e (diff) |
power: smb349: addition of regulator interface
Addition of reglator interface to detect the usb cable
plug/unplug detection.
Bug 961166
Bug 966874
Change-Id: Ida297bc39df9aca8cffe60c29bc24f2d32819f56
Signed-off-by: Syed Rafiuddin <srafiuddin@nvidia.com>
Signed-off-by: Chandler Zhang <chazhang@nvidia.com>
Reviewed-on: http://git-master/r/96440
Reviewed-by: Automatic_Commit_Validation_User
Reviewed-by: Sachin Nikam <snikam@nvidia.com>
Diffstat (limited to 'drivers/power')
-rw-r--r-- | drivers/power/smb349-charger.c | 266 |
1 files changed, 124 insertions, 142 deletions
diff --git a/drivers/power/smb349-charger.c b/drivers/power/smb349-charger.c index 1f230baadcb5..3013e576a463 100644 --- a/drivers/power/smb349-charger.c +++ b/drivers/power/smb349-charger.c @@ -84,7 +84,6 @@ static struct smb349_charger *charger; static int smb349_configure_charger(struct i2c_client *client, int value); -static int smb349_configure_interrupts(struct i2c_client *client); static int smb349_read(struct i2c_client *client, int reg) { @@ -158,16 +157,6 @@ int smb349_volatile_writes(struct i2c_client *client, uint8_t value) return ret; } -static void smb349_clear_interrupts(struct i2c_client *client) -{ - uint8_t val, buf[6]; - - val = i2c_smbus_read_i2c_block_data(client, SMB349_INTR_STS_A, 6, buf); - if (val < 0) - dev_err(&client->dev, "%s(): Failed in clearing interrupts\n", - __func__); -} - static int smb349_configure_otg(struct i2c_client *client, int enable) { int ret = 0; @@ -283,59 +272,6 @@ error: return ret; } -static irqreturn_t smb349_status_isr(int irq, void *dev_id) -{ - struct i2c_client *client = charger->client; - int ret, val; - - val = smb349_read(client, SMB349_STS_REG_D); - if (val < 0) { - dev_err(&client->dev, "%s(): Failed in reading register" - "0x%02x\n", __func__, SMB349_STS_REG_D); - goto irq_error; - } else if (val != 0) { - if (val & DEDICATED_CHARGER) - charger->chrg_type = AC; - else if (val & CHRG_DOWNSTRM_PORT) - charger->chrg_type = USB; - - /* configure charger */ - ret = smb349_configure_charger(client, 1); - if (ret < 0) { - dev_err(&client->dev, "%s() error in configuring" - "charger..\n", __func__); - goto irq_error; - } - - charger->state = progress; - } else { - charger->state = stopped; - - /* Disable charger */ - ret = smb349_configure_charger(client, 0); - if (ret < 0) { - dev_err(&client->dev, "%s() error in configuring" - "charger..\n", __func__); - goto irq_error; - } - - ret = smb349_configure_interrupts(client); - if (ret < 0) { - dev_err(&client->dev, "%s() error in configuring" - "charger..\n", __func__); - goto irq_error; - } - - } - - if (charger->charger_cb) - charger->charger_cb(charger->state, charger->chrg_type, - charger->charger_cb_data); -irq_error: - smb349_clear_interrupts(client); - return IRQ_HANDLED; -} - int update_charger_status(void) { struct i2c_client *client = charger->client; @@ -349,28 +285,12 @@ int update_charger_status(void) } else if (val != 0) { if (val & DEDICATED_CHARGER) charger->chrg_type = AC; - else if (val & CHRG_DOWNSTRM_PORT) + else charger->chrg_type = USB; - /* configure charger */ - ret = smb349_configure_charger(client, 1); - if (ret < 0) { - dev_err(&client->dev, "%s() error in configuring" - "charger..\n", __func__); - goto ret_error; - } - charger->state = progress; } else { charger->state = stopped; - - /* Disable charger */ - ret = smb349_configure_charger(client, 0); - if (ret < 0) { - dev_err(&client->dev, "%s() error in configuring" - "charger..\n", __func__); - goto ret_error; - } } if (charger->charger_cb) @@ -413,43 +333,6 @@ int smb349_battery_online(void) return 1; } -static int smb349_configure_interrupts(struct i2c_client *client) -{ - int ret = 0; - - /* Enable volatile writes to registers */ - ret = smb349_volatile_writes(client, SMB349_ENABLE_WRITE); - if (ret < 0) { - dev_err(&client->dev, "%s() error in configuring charger..\n", - __func__); - goto error; - } - - ret = smb349_update_reg(client, SMB349_FAULT_INTR, 0xff); - if (ret < 0) { - dev_err(&client->dev, "%s(): Failed in writing register" - "0x%02x\n", __func__, SMB349_CMD_REG); - goto error; - } - - ret = smb349_update_reg(client, SMB349_STS_INTR_1, 0xff); - if (ret < 0) { - dev_err(&client->dev, "%s: err %d\n", __func__, ret); - goto error; - } - - /* Disable volatile writes to registers */ - ret = smb349_volatile_writes(client, SMB349_DISABLE_WRITE); - if (ret < 0) { - dev_err(&client->dev, "%s() error in configuring charger..\n", - __func__); - goto error; - } - -error: - return ret; -} - static void smb349_otg_status(enum usb_otg_state to, enum usb_otg_state from, void *data) { struct i2c_client *client = charger->client; @@ -482,19 +365,67 @@ static void smb349_otg_status(enum usb_otg_state to, enum usb_otg_state from, vo if (ret < 0) dev_err(&client->dev, "%s() error in configuring" "otg..\n", __func__); + } +} - ret = smb349_configure_interrupts(client); - if (ret < 0) +static int smb349_enable_charging(struct regulator_dev *rdev, + int min_uA, int max_uA) +{ + struct i2c_client *client; + int ret; + + if(!charger) + return -ENODEV; + else + client = charger->client; + + if (!max_uA) { + charger->state = stopped; + /* Disable charger */ + ret = smb349_configure_charger(client, 0); + if (ret < 0) { dev_err(&client->dev, "%s() error in configuring" - "otg..\n", __func__); + "charger..\n", __func__); + return ret; + } + } else { + ret = smb349_read(client, SMB349_STS_REG_D); + if (ret < 0) { + dev_err(&client->dev, "%s(): Failed in reading register" + "0x%02x\n", __func__, SMB349_STS_REG_D); + return ret; + } else if (ret != 0) { + if (ret & DEDICATED_CHARGER) + charger->chrg_type = AC; + else + charger->chrg_type = USB; + + /* configure charger */ + ret = smb349_configure_charger(client, 1); + if (ret < 0) { + dev_err(&client->dev, "%s() error in" + "configuring charger..\n", __func__); + return ret; + } + charger->state = progress; + } } + if (charger->charger_cb) + charger->charger_cb(charger->state, charger->chrg_type, + charger->charger_cb_data); +return 0; } +static struct regulator_ops smb349_tegra_regulator_ops = { + .set_current_limit = smb349_enable_charging, +}; + static int __devinit smb349_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); - int ret, irq_num; + struct smb349_charger_platform_data *pdata; + int ret; if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE)) return -EIO; @@ -505,6 +436,7 @@ static int __devinit smb349_probe(struct i2c_client *client, charger->client = client; charger->dev = &client->dev; + pdata = client->dev.platform_data; i2c_set_clientdata(client, charger); /* Check battery presence */ @@ -512,37 +444,87 @@ static int __devinit smb349_probe(struct i2c_client *client, dev_err(&client->dev, "%s() No Battery present, exiting..\n", __func__); ret = -ENODEV; - goto error; + goto regulator_error; } - ret = register_otg_callback(smb349_otg_status, charger); - if (ret < 0) - goto error; - - ret = smb349_configure_charger(client, 1); - if (ret < 0) - return ret; + charger->reg_desc.name = "vbus_charger"; + charger->reg_desc.ops = &smb349_tegra_regulator_ops; + charger->reg_desc.type = REGULATOR_CURRENT; + charger->reg_desc.id = pdata->regulator_id; + charger->reg_desc.type = REGULATOR_CURRENT; + charger->reg_desc.owner = THIS_MODULE; + + charger->reg_init_data.supply_regulator = NULL; + charger->reg_init_data.num_consumer_supplies = + pdata->num_consumer_supplies; + charger->reg_init_data.regulator_init = NULL; + charger->reg_init_data.consumer_supplies = + pdata->consumer_supplies; + charger->reg_init_data.driver_data = charger; + charger->reg_init_data.constraints.name = "vbus_charger"; + charger->reg_init_data.constraints.min_uA = 0; + charger->reg_init_data.constraints.max_uA = + pdata->max_charge_current_mA * 1000; + + charger->reg_init_data.constraints.valid_modes_mask = + REGULATOR_MODE_NORMAL | + REGULATOR_MODE_STANDBY; + + charger->reg_init_data.constraints.valid_ops_mask = + REGULATOR_CHANGE_MODE | + REGULATOR_CHANGE_STATUS | + REGULATOR_CHANGE_CURRENT; + + charger->rdev = regulator_register(&charger->reg_desc, charger->dev, + &charger->reg_init_data, charger); + if (IS_ERR(charger->rdev)) { + dev_err(&client->dev, "failed to register %s\n", + charger->reg_desc.name); + ret = PTR_ERR(charger->rdev); + goto regulator_error; + } - ret = smb349_configure_interrupts(client); + /* disable OTG */ + ret = smb349_configure_otg(client, 0); if (ret < 0) { - dev_err(&client->dev, "%s() error in configuring charger..\n", - __func__); + dev_err(&client->dev, "%s() error in configuring" + "charger..\n", __func__); goto error; } - irq_num = gpio_to_irq(client->irq); - ret = request_threaded_irq(irq_num, - NULL, smb349_status_isr, IRQ_TYPE_EDGE_FALLING, - "smb349", charger); - if (ret) { - dev_err(&client->dev, "%s(): Failed in requesting isr\n", - __func__); + ret = smb349_read(client, SMB349_STS_REG_D); + if (ret < 0) { + dev_err(&client->dev, "%s(): Failed in reading register" + "0x%02x\n", __func__, SMB349_STS_REG_D); goto error; + } else if (ret != 0) { + /* configure charger */ + ret = smb349_configure_charger(client, 1); + if (ret < 0) { + dev_err(&client->dev, "%s() error in configuring" + "charger..\n", __func__); + goto error; + } + } else { + /* disable charger */ + ret = smb349_configure_charger(client, 0); + if (ret < 0) { + dev_err(&client->dev, "%s() error in configuring" + "charger..\n", __func__); + goto error; + } } + ret = register_otg_callback(smb349_otg_status, charger); + if (ret < 0) + goto error; + return 0; error: + regulator_unregister(charger->rdev); +regulator_error: kfree(charger); + charger = NULL; return ret; } @@ -550,7 +532,7 @@ static int __devexit smb349_remove(struct i2c_client *client) { struct smb349_charger *charger = i2c_get_clientdata(client); - free_irq(gpio_to_irq(client->irq), charger); + regulator_unregister(charger->rdev); kfree(charger); return 0; @@ -575,7 +557,7 @@ static int __init smb349_init(void) { return i2c_add_driver(&smb349_i2c_driver); } -module_init(smb349_init); +subsys_initcall(smb349_init); static void __exit smb349_exit(void) { |