blob: 3642f653fcb55687beb004dd2e26d4e17ce3ab83 [file] [log] [blame]
/* Copyright (c) 2014, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
* only version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#define pr_fmt(fmt) "%s: " fmt, __func__
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/of.h>
#include <linux/of_gpio.h>
#include <linux/of_device.h>
#include <linux/err.h>
#include <linux/i2c.h>
#include <linux/regmap.h>
#include <linux/regulator/of_regulator.h>
#include <linux/regulator/driver.h>
#include <linux/regulator/machine.h>
#include <linux/bitops.h>
#include <linux/types.h>
struct tps65132_regulator {
struct regulator_init_data *init_data;
struct regulator_dev *rdev;
struct device_node *node;
struct regulator_desc rdesc;
struct tps65132_chip *chip;
const char *name;
u8 vol_reg;
u8 dischg_bit_pos;
bool dischg_en;
u8 ctrl_reg;
u8 wrt_en_bit_pos;
u8 read_eeprom_bit_pos;
int en_gpio;
enum of_gpio_flags gpio_flags;
bool is_enabled;
int curr_uV;
u8 vol_set_val;
bool vol_set_postpone;
};
struct tps65132_chip {
struct tps65132_regulator *vreg;
struct regulator *i2c_pwr;
struct regmap *regmap;
struct device *dev;
u8 num_regulators;
u8 apps_cfg;
u8 apps_dischg_reg;
u8 apps_cfg_bit_pos;
u8 apps_dischg_val;
bool apps_dischg_cfg_postpone;
bool en_gpio_lpm;
};
#define TPS65132_REG_VPOS 0x00
#define TPS65132_REG_VNEG 0x01
#define TPS65132_VOLTAGE_MASK 0x1f
#define TPS65132_REG_APPS_DISCHARGE 0x03
#define TPS65132_DISCHARGE_NEG_BIT 0
#define TPS65132_DISCHARGE_POS_BIT 1
#define TPS65132_APPSCFG_BIT 6
#define TPS65132_REG_CTRL 0xff
#define TPS65132_WRITE_EN_BIT 7
#define TPS65132_VOLTAGE_MIN 4000000
#define TPS65132_VOLTAGE_MAX 6000000
#define TPS65132_VOLTAGE_STEP 100000
#define TPS65132_VOLTAGE_LEVELS \
((TPS65132_VOLTAGE_MAX - TPS65132_VOLTAGE_MIN) \
/ TPS65132_VOLTAGE_STEP + 1)
#define TPS65132_CTRL_READ_DAC 0
#define TPS65132_CTRL_READ_EEPROM 1
#define TPS65132_NEG_TABLET_CURR_LIMIT_UA 80000
#define TPS65132_NEG_SMARTPHONE_CURR_LIMIT_UA 40000
#define TPS65132_POS_CURR_LIMIT_UA 200000
#define I2C_VOLTAGE_LEVEL 1800000
enum {
TPS65132_POSITIVE_BOOST = 0,
TPS65132_NEGATIVE_BOOST,
};
static struct of_regulator_match tps65132_reg_matches[] = {
{ .name = "pos-boost", .driver_data = (void *)TPS65132_POSITIVE_BOOST },
{ .name = "neg-boost", .driver_data = (void *)TPS65132_NEGATIVE_BOOST },
};
static int tps65132_regulator_disable(struct regulator_dev *rdev)
{
struct tps65132_regulator *vreg = rdev_get_drvdata(rdev);
struct tps65132_chip *chip = vreg->chip;
if (chip->en_gpio_lpm)
gpio_direction_input(vreg->en_gpio);
else
gpio_set_value_cansleep(vreg->en_gpio,
vreg->gpio_flags & OF_GPIO_ACTIVE_LOW ? 1 : 0);
vreg->is_enabled = false;
return 0;
}
static int tps65132_regulator_enable(struct regulator_dev *rdev)
{
struct tps65132_regulator *vreg = rdev_get_drvdata(rdev);
struct tps65132_chip *chip = vreg->chip;
int rc;
if (chip->en_gpio_lpm)
gpio_direction_output(vreg->en_gpio,
vreg->gpio_flags & OF_GPIO_ACTIVE_LOW ? 0 : 1);
else
gpio_set_value_cansleep(vreg->en_gpio,
vreg->gpio_flags & OF_GPIO_ACTIVE_LOW ? 0 : 1);
vreg->is_enabled = true;
if (chip->apps_dischg_cfg_postpone) {
rc = regmap_write(chip->regmap, chip->apps_dischg_reg,
chip->apps_dischg_val);
if (rc) {
pr_err("apps_dischg set failed, rc = %d\n", rc);
return rc;
}
chip->apps_dischg_cfg_postpone = false;
}
if (vreg->vol_set_postpone) {
rc = regmap_write(rdev->regmap, vreg->vol_reg,
vreg->vol_set_val);
if (rc) {
pr_err("set voltage failed, rc = %d\n", rc);
return rc;
}
vreg->vol_set_postpone = false;
}
return 0;
}
static int tps65132_regulator_get_voltage(struct regulator_dev *rdev)
{
struct tps65132_regulator *vreg = rdev_get_drvdata(rdev);
int rc, val;
if (!rdev->regmap) {
pr_err("regmap not found\n");
return -EINVAL;
}
if (!vreg->is_enabled)
return vreg->curr_uV;
rc = regmap_write(rdev->regmap, vreg->ctrl_reg, TPS65132_CTRL_READ_DAC);
if (rc) {
pr_err("failed to write reg %d, rc = %d\n", vreg->ctrl_reg, rc);
return rc;
}
rc = regmap_read(rdev->regmap, vreg->vol_reg, &val);
if (rc) {
pr_err("read reg %d failed, rc = %d\n", vreg->vol_reg, rc);
return rc;
} else {
vreg->curr_uV = (val & TPS65132_VOLTAGE_MASK) *
TPS65132_VOLTAGE_STEP + TPS65132_VOLTAGE_MIN;
}
return vreg->curr_uV;
}
static int tps65132_regulator_set_voltage(struct regulator_dev *rdev,
int min_uV, int max_uV, unsigned *selector)
{
struct tps65132_regulator *vreg = rdev_get_drvdata(rdev);
int val, new_uV, rc;
if (!rdev->regmap) {
pr_err("regmap not found\n");
return -EINVAL;
}
val = DIV_ROUND_UP(min_uV - TPS65132_VOLTAGE_MIN,
TPS65132_VOLTAGE_STEP);
val = val & TPS65132_VOLTAGE_MASK;
new_uV = TPS65132_VOLTAGE_MIN + (val * TPS65132_VOLTAGE_STEP);
if (new_uV > max_uV) {
pr_err("failed to set voltage (%d %d)\n", min_uV, max_uV);
return -EINVAL;
}
if (!vreg->is_enabled) {
vreg->vol_set_val = val;
vreg->vol_set_postpone = true;
} else {
rc = regmap_write(rdev->regmap, vreg->vol_reg, val);
if (rc) {
pr_err("failed to write reg %d, rc = %d\n",
vreg->vol_reg, rc);
return rc;
}
}
vreg->curr_uV = new_uV;
*selector = val;
return 0;
}
static int tps65132_regulator_list_voltage(struct regulator_dev *rdev,
unsigned selector)
{
if (selector >= TPS65132_VOLTAGE_LEVELS)
return 0;
return selector * TPS65132_VOLTAGE_STEP + TPS65132_VOLTAGE_MIN;
}
static int tps65132_regulator_is_enabled(struct regulator_dev *rdev)
{
struct tps65132_regulator *vreg = rdev_get_drvdata(rdev);
return vreg->is_enabled ? 1 : 0;
}
static struct regulator_ops tps65132_ops = {
.set_voltage = tps65132_regulator_set_voltage,
.get_voltage = tps65132_regulator_get_voltage,
.list_voltage = tps65132_regulator_list_voltage,
.enable = tps65132_regulator_enable,
.disable = tps65132_regulator_disable,
.is_enabled = tps65132_regulator_is_enabled,
};
static int tps65132_regulator_gpio_init(struct tps65132_chip *chip)
{
struct tps65132_regulator *vreg;
u32 gpio;
enum of_gpio_flags flags;
int state;
int i, rc = 0;
for (i = 0; i < chip->num_regulators; i++) {
vreg = &chip->vreg[i];
gpio = vreg->en_gpio;
flags = vreg->gpio_flags;
if (gpio_is_valid(gpio)) {
rc = devm_gpio_request(chip->dev, gpio, vreg->name);
if (rc < 0) {
pr_err("gpio %d request failed, rc = %d\n",
gpio, rc);
return rc;
}
state = gpio_get_value_cansleep(gpio);
if (state < 0) {
pr_err("gpio %d: get value failed, rc = %d\n",
gpio, state);
return state;
}
rc = gpio_direction_output(gpio, state);
if (rc < 0) {
pr_err("gpio %d set output failed, rc = %d\n",
gpio, rc);
return rc;
}
if (((flags & OF_GPIO_ACTIVE_LOW) && (state == 0)) ||
(!(flags & OF_GPIO_ACTIVE_LOW) && (state == 1)))
vreg->is_enabled = true;
} else {
pr_err("gpio %d is invalid for %s EN-pin\n",
gpio, vreg->name);
return -EINVAL;
}
}
return rc;
}
static int tps65132_regulator_apps_dischg_config(struct tps65132_chip *chip)
{
struct tps65132_regulator *vreg;
u8 value = 0;
bool online = false;
int i, rc = 0;
if (chip->apps_cfg > 0)
value = BIT(chip->apps_cfg_bit_pos);
for (i = 0; i < chip->num_regulators; i++) {
vreg = &chip->vreg[i];
if (vreg->dischg_en)
value |= BIT(vreg->dischg_bit_pos);
if (vreg->is_enabled)
online = true;
}
if (online) {
rc = regmap_write(chip->regmap, chip->apps_dischg_reg, value);
if (rc)
pr_err("write reg %d failed, rc = %d\n",
chip->apps_dischg_reg, rc);
} else {
chip->apps_dischg_cfg_postpone = true;
chip->apps_dischg_val = value;
}
return 0;
}
static int tps65132_regulator_hw_init(struct tps65132_chip *chip)
{
int rc;
struct regulator *i2c_pwr = chip->i2c_pwr;
rc = tps65132_regulator_gpio_init(chip);
if (rc) {
pr_err("gpios initialize failed, rc = %d\n", rc);
return rc;
}
if (i2c_pwr) {
if (regulator_count_voltages(i2c_pwr) > 0) {
rc = regulator_set_voltage(i2c_pwr,
I2C_VOLTAGE_LEVEL, I2C_VOLTAGE_LEVEL);
if (rc < 0) {
pr_err("set i2c-pwr voltage failed, rc = %d\n",
rc);
return rc;
}
}
rc = regulator_enable(i2c_pwr);
if (rc) {
pr_err("enable i2c-pwr voltage failed, rc = %d\n", rc);
return rc;
}
}
rc = tps65132_regulator_apps_dischg_config(chip);
if (rc)
pr_err("appscfg set failed, rc = %d\n", rc);
return rc;
}
static int tps65132_parse_dt(struct tps65132_chip *chip,
struct i2c_client *client)
{
struct device_node *node;
struct of_regulator_match *match;
int type, i, rc;
u32 current_limit;
if (!client->dev.of_node) {
pr_err("device node missing\n");
return -EINVAL;
}
node = of_find_node_by_name(client->dev.of_node, "regulators");
if (!node) {
pr_err("get regulators node failed\n");
return -EINVAL;
}
rc = of_regulator_match(&client->dev, node, tps65132_reg_matches,
ARRAY_SIZE(tps65132_reg_matches));
if (rc < 0) {
pr_err("regulator match failed, rc = %d\n", rc);
return rc;
}
chip->num_regulators = rc;
chip->vreg = devm_kzalloc(&client->dev, chip->num_regulators *
sizeof(struct tps65132_regulator),
GFP_KERNEL);
if (!chip->vreg) {
pr_err("memory allocation failed for vreg\n");
return -ENOMEM;
}
if (of_find_property(client->dev.of_node, "i2c-pwr-supply", NULL)) {
chip->i2c_pwr = devm_regulator_get(&client->dev, "i2c-pwr");
if (IS_ERR_OR_NULL(chip->i2c_pwr)) {
rc = PTR_RET(chip->i2c_pwr);
if (rc != EPROBE_DEFER)
pr_err("get i2c_pwr failed, rc = %d\n", rc);
return rc;
}
}
chip->en_gpio_lpm = of_property_read_bool(client->dev.of_node,
"ti,en-gpio-lpm");
for (i = 0; i < chip->num_regulators; i++) {
match = &tps65132_reg_matches[i];
if (!match->init_data)
continue;
match->init_data->constraints.input_uV =
match->init_data->constraints.max_uV;
match->init_data->constraints.valid_ops_mask =
REGULATOR_CHANGE_VOLTAGE |
REGULATOR_CHANGE_STATUS;
chip->vreg[i].init_data = match->init_data;
chip->vreg[i].node = match->of_node;
chip->vreg[i].chip = chip;
chip->vreg[i].name = match->init_data->constraints.name;
chip->vreg[i].ctrl_reg = TPS65132_REG_CTRL;
chip->vreg[i].wrt_en_bit_pos = TPS65132_WRITE_EN_BIT;
chip->vreg[i].read_eeprom_bit_pos =
TPS65132_WRITE_EN_BIT;
chip->vreg[i].dischg_en = of_property_read_bool(
match->of_node, "ti,discharge-enable");
rc = of_property_read_u32(match->of_node, "ti,enable-time",
&chip->vreg[i].rdesc.enable_time);
if (rc < 0) {
pr_debug("ti,enable-time read failed, rc = %d\n", rc);
chip->vreg[i].rdesc.enable_time = 800;
}
rc = of_property_read_u32(match->of_node, "ti,current-limit",
&current_limit);
type = (uintptr_t)match->driver_data;
if (type == TPS65132_POSITIVE_BOOST) {
chip->vreg[i].vol_reg = TPS65132_REG_VPOS;
chip->vreg[i].dischg_bit_pos =
TPS65132_DISCHARGE_POS_BIT;
if (!rc && (current_limit !=
TPS65132_POS_CURR_LIMIT_UA)) {
pr_err("current limit %duA is invalid for postive boost\n",
current_limit);
return -EINVAL;
}
} else if (type == TPS65132_NEGATIVE_BOOST) {
chip->vreg[i].vol_reg = TPS65132_REG_VNEG;
chip->vreg[i].dischg_bit_pos =
TPS65132_DISCHARGE_NEG_BIT;
if (!rc && (current_limit !=
TPS65132_NEG_TABLET_CURR_LIMIT_UA) &&
(current_limit !=
TPS65132_NEG_SMARTPHONE_CURR_LIMIT_UA)) {
pr_err("current limit %duA is invalid for negative boost\n",
current_limit);
return -EINVAL;
} else if (!rc && (current_limit ==
TPS65132_NEG_TABLET_CURR_LIMIT_UA)) {
chip->apps_cfg = 1;
}
} else {
pr_err("unknown regulator type: %d\n", type);
return -EINVAL;
}
rc = 0;
chip->vreg[i].en_gpio = of_get_named_gpio_flags(
match->of_node, "ti,en-gpio", 0,
&chip->vreg[i].gpio_flags);
if (chip->vreg[i].en_gpio < 0) {
pr_err("get ti,en-gpio failed, rc = %d\n",
chip->vreg[i].en_gpio);
return chip->vreg[i].en_gpio;
}
}
chip->apps_dischg_reg = TPS65132_REG_APPS_DISCHARGE;
chip->apps_cfg_bit_pos = TPS65132_APPSCFG_BIT;
return rc;
}
static struct regmap_config tps65132_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
};
static int tps65132_regulator_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct tps65132_chip *chip;
struct regulator_config config = {};
struct regulator_desc *rdesc;
int i, j, rc;
chip = devm_kzalloc(&client->dev, sizeof(struct tps65132_chip),
GFP_KERNEL);
if (!chip) {
pr_err("memory allocation failed for tps65132_chip\n");
return -ENOMEM;
}
rc = tps65132_parse_dt(chip, client);
if (rc) {
pr_err("parse device tree failed for tps65132, rc = %d\n",
rc);
return rc;
}
chip->regmap = devm_regmap_init_i2c(client, &tps65132_regmap_config);
if (IS_ERR(chip->regmap)) {
pr_err("init regmap failed for tps65132, rc = %ld\n",
PTR_ERR(chip->regmap));
return PTR_ERR(chip->regmap);
}
chip->dev = &client->dev;
rc = tps65132_regulator_hw_init(chip);
if (rc < 0) {
pr_err("hardware init failed for tps65132, rc = %d\n", rc);
return rc;
}
i2c_set_clientdata(client, chip);
for (i = 0; i < chip->num_regulators; i++) {
config.dev = &client->dev;
config.init_data = chip->vreg[i].init_data;
config.regmap = chip->regmap;
config.driver_data = &chip->vreg[i];
config.of_node = chip->vreg[i].node;
rdesc = &chip->vreg[i].rdesc;
rdesc->name = chip->vreg[i].name;
rdesc->type = REGULATOR_VOLTAGE;
rdesc->owner = THIS_MODULE;
rdesc->n_voltages = TPS65132_VOLTAGE_LEVELS;
if (of_get_property(client->dev.of_node, "vin-supply", NULL))
rdesc->supply_name = "vin";
rdesc->ops = &tps65132_ops;
chip->vreg[i].rdev = regulator_register(rdesc, &config);
if (IS_ERR(chip->vreg[i].rdev)) {
pr_err("regulator register failed, rc = %ld\n",
PTR_ERR(chip->vreg[i].rdev));
for (j = i - 1; j >= 0; j--)
regulator_unregister(chip->vreg[j].rdev);
return PTR_ERR(chip->vreg[i].rdev);
}
}
return 0;
}
static int tps65132_regulator_remove(struct i2c_client *client)
{
struct tps65132_chip *chip = i2c_get_clientdata(client);
struct regulator *i2c_pwr = chip->i2c_pwr;
int i;
if (i2c_pwr)
regulator_disable(i2c_pwr);
for (i = 0; i < chip->num_regulators; i++)
regulator_unregister(chip->vreg[i].rdev);
return 0;
}
static struct of_device_id tps65132_match_table[] = {
{ .compatible = "ti,tps65132", },
{},
};
MODULE_DEVICE_TABLE(of, tps65132_match_table);
static const struct i2c_device_id tps65132_id[] = {
{"tps65132", -1},
{ },
};
static int tps65132_suspend(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
struct tps65132_chip *chip = i2c_get_clientdata(client);
int rc = 0;
if (chip->i2c_pwr)
rc = regulator_disable(chip->i2c_pwr);
return rc;
}
static int tps65132_resume(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
struct tps65132_chip *chip = i2c_get_clientdata(client);
int rc = 0;
if (chip->i2c_pwr)
rc = regulator_enable(chip->i2c_pwr);
return rc;
}
static const struct dev_pm_ops tps65132_pm_ops = {
.resume = tps65132_resume,
.suspend = tps65132_suspend,
};
static struct i2c_driver tps65132_regulator_driver = {
.driver = {
.name = "tps65132",
.owner = THIS_MODULE,
.of_match_table = tps65132_match_table,
.pm = &tps65132_pm_ops,
},
.probe = tps65132_regulator_probe,
.remove = tps65132_regulator_remove,
.id_table = tps65132_id,
};
static int __init tps65132_init(void)
{
return i2c_add_driver(&tps65132_regulator_driver);
}
subsys_initcall(tps65132_init);
static void __exit tps65132_exit(void)
{
i2c_del_driver(&tps65132_regulator_driver);
}
module_exit(tps65132_exit);
MODULE_DESCRIPTION("TI TPS65132 regulator driver");
MODULE_LICENSE("GPL v2");