Port TPS6518X driver
parent
5c76066147
commit
4168ae8de1
|
@ -834,6 +834,15 @@ config SENSORS_MAX17135
|
|||
This driver can also be built as a module. If so, the module
|
||||
will be called max17135_sensor.
|
||||
|
||||
config SENSORS_TPS6518X
|
||||
tristate "Texas Instruments TPS6518X EPD temperature sensor"
|
||||
depends on I2C
|
||||
help
|
||||
If you say yes here you get support for TPS6518X PMIC sensor.
|
||||
|
||||
This driver can also be built as a module. If so, the module
|
||||
will be called tps6518x_sensor.
|
||||
|
||||
config SENSORS_MAX197
|
||||
tristate "Maxim MAX197 and compatibles"
|
||||
help
|
||||
|
|
|
@ -114,6 +114,7 @@ obj-$(CONFIG_SENSORS_MAX16065) += max16065.o
|
|||
obj-$(CONFIG_SENSORS_MAX1619) += max1619.o
|
||||
obj-$(CONFIG_SENSORS_MAX1668) += max1668.o
|
||||
obj-$(CONFIG_SENSORS_MAX17135) += max17135-hwmon.o
|
||||
obj-$(CONFIG_SENSORS_TPS6518X) += tps6518x-hwmon.o
|
||||
obj-$(CONFIG_SENSORS_MAX197) += max197.o
|
||||
obj-$(CONFIG_SENSORS_MAX31722) += max31722.o
|
||||
obj-$(CONFIG_SENSORS_MAX6639) += max6639.o
|
||||
|
|
|
@ -0,0 +1,319 @@
|
|||
/*
|
||||
* Copyright (C) 2010 Freescale Semiconductor, Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
/*
|
||||
* tps65185.c
|
||||
*
|
||||
* Based on the MAX1619 driver.
|
||||
* Copyright (C) 2003-2004 Alexey Fisher <fishor@mail.ru>
|
||||
* Jean Delvare <khali@linux-fr.org>
|
||||
*
|
||||
* The TPS65185 is a sensor chip made by Texass Instruments.
|
||||
* It reports up to two temperatures (its own plus up to
|
||||
* one external one).
|
||||
*/
|
||||
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/jiffies.h>
|
||||
#include <linux/hwmon.h>
|
||||
#include <linux/hwmon-sysfs.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/sysfs.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/mfd/tps6518x.h>
|
||||
|
||||
/*
|
||||
* Conversions
|
||||
*/
|
||||
static int temp_from_reg(int val)
|
||||
{
|
||||
return val;
|
||||
}
|
||||
|
||||
/*
|
||||
* Functions declaration
|
||||
*/
|
||||
static int tps6518x_sensor_probe(struct platform_device *pdev);
|
||||
static int tps6518x_sensor_remove(struct platform_device *pdev);
|
||||
|
||||
static const struct platform_device_id tps6518x_sns_id[] = {
|
||||
{ "tps6518x-sns", 0},
|
||||
{ /* sentinel */ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(platform, tps6518x_sns_id);
|
||||
|
||||
/*
|
||||
* Driver data (common to all clients)
|
||||
*/
|
||||
static struct platform_driver tps6518x_sensor_driver = {
|
||||
.probe = tps6518x_sensor_probe,
|
||||
.remove = tps6518x_sensor_remove,
|
||||
.id_table = tps6518x_sns_id,
|
||||
.driver = {
|
||||
.name = "tps6518x_sensor",
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Client data (each client gets its own)
|
||||
*/
|
||||
struct tps6518x_data {
|
||||
struct device *hwmon_dev;
|
||||
};
|
||||
|
||||
/*
|
||||
* Sysfs stuff
|
||||
*/
|
||||
static ssize_t show_temp_input(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
unsigned int reg_val;
|
||||
/*
|
||||
* begin Temperature conversion
|
||||
*/
|
||||
tps6518x_reg_read(REG_TPS6518x_REVID,®_val);
|
||||
switch (reg_val & 0xff)
|
||||
{
|
||||
case TPS65180_PASS1 :
|
||||
case TPS65180_PASS2 :
|
||||
case TPS65181_PASS1 :
|
||||
case TPS65181_PASS2 :
|
||||
reg_val = 0x80;
|
||||
tps6518x_reg_write(REG_TPS65180_TMST_CONFIG, reg_val);
|
||||
// wait for completion completed
|
||||
while ((0x20 & reg_val) == 0)
|
||||
{
|
||||
msleep(1);
|
||||
tps6518x_reg_read(REG_TPS65180_TMST_CONFIG, ®_val);
|
||||
}
|
||||
break;
|
||||
case TPS65185_PASS0 :
|
||||
case TPS65186_PASS0 :
|
||||
case TPS65185_PASS1 :
|
||||
case TPS65186_PASS1 :
|
||||
case TPS65185_PASS2 :
|
||||
case TPS65186_PASS2 :
|
||||
reg_val = 0x80;
|
||||
tps6518x_reg_write(REG_TPS65185_TMST1, reg_val);
|
||||
// wait for completion completed
|
||||
while ((0x20 & reg_val) == 0)
|
||||
{
|
||||
msleep(1);
|
||||
tps6518x_reg_read(REG_TPS65185_TMST1, ®_val);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
tps6518x_reg_read(REG_TPS6518x_TMST_VAL, ®_val);
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n", temp_from_reg(reg_val));
|
||||
}
|
||||
|
||||
static ssize_t show_intr_regs(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
unsigned int reg_val;
|
||||
unsigned int intr_reg_val;
|
||||
/*
|
||||
* get the interrupt status register value
|
||||
*/
|
||||
tps6518x_reg_read(REG_TPS6518x_REVID,®_val);
|
||||
switch (reg_val & 0xff)
|
||||
{
|
||||
case TPS65180_PASS1 :
|
||||
case TPS65180_PASS2 :
|
||||
case TPS65181_PASS1 :
|
||||
case TPS65181_PASS2 :
|
||||
tps6518x_reg_read(REG_TPS65180_INT1, &intr_reg_val);
|
||||
tps6518x_reg_read(REG_TPS65180_INT2, ®_val);
|
||||
intr_reg_val |= reg_val<<8;
|
||||
break;
|
||||
case TPS65185_PASS0 :
|
||||
case TPS65186_PASS0 :
|
||||
case TPS65185_PASS1 :
|
||||
case TPS65186_PASS1 :
|
||||
case TPS65185_PASS2 :
|
||||
case TPS65186_PASS2 :
|
||||
tps6518x_reg_read(REG_TPS65185_INT1, &intr_reg_val);
|
||||
tps6518x_reg_read(REG_TPS65185_INT2, ®_val);
|
||||
intr_reg_val |= reg_val<<8;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n", intr_reg_val);
|
||||
}
|
||||
|
||||
static ssize_t show_vcom(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
unsigned int reg_val;
|
||||
unsigned int vcom_reg_val;
|
||||
/*
|
||||
* get the vcom registers
|
||||
*/
|
||||
tps6518x_reg_read(REG_TPS6518x_REVID,®_val);
|
||||
switch (reg_val & 0xff)
|
||||
{
|
||||
case TPS65180_PASS1 :
|
||||
case TPS65180_PASS2 :
|
||||
case TPS65181_PASS1 :
|
||||
case TPS65181_PASS2 :
|
||||
tps6518x_reg_read(REG_TPS65180_VCOM_ADJUST, &vcom_reg_val);
|
||||
break;
|
||||
case TPS65185_PASS0 :
|
||||
case TPS65186_PASS0 :
|
||||
case TPS65185_PASS1 :
|
||||
case TPS65186_PASS1 :
|
||||
case TPS65185_PASS2 :
|
||||
case TPS65186_PASS2 :
|
||||
tps6518x_reg_read(REG_TPS65185_VCOM1, &vcom_reg_val);
|
||||
tps6518x_reg_read(REG_TPS65185_VCOM2, ®_val);
|
||||
vcom_reg_val |= reg_val<<8;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n", vcom_reg_val);
|
||||
}
|
||||
|
||||
static ssize_t set_vcom(struct device *dev,
|
||||
struct device_attribute *attr, const char *buf, size_t count)
|
||||
{
|
||||
unsigned int reg_val;
|
||||
long vcom_reg_val = simple_strtol(buf,NULL,10);
|
||||
/*
|
||||
* get the interrupt status register value
|
||||
*/
|
||||
tps6518x_reg_read(REG_TPS6518x_REVID,®_val);
|
||||
switch (reg_val & 0xff)
|
||||
{
|
||||
case TPS65180_PASS1 :
|
||||
case TPS65180_PASS2 :
|
||||
case TPS65181_PASS1 :
|
||||
case TPS65181_PASS2 :
|
||||
tps6518x_reg_write(REG_TPS65180_VCOM_ADJUST, vcom_reg_val&0xff);
|
||||
break;
|
||||
case TPS65185_PASS0 :
|
||||
case TPS65186_PASS0 :
|
||||
case TPS65185_PASS1 :
|
||||
case TPS65186_PASS1 :
|
||||
case TPS65185_PASS2 :
|
||||
case TPS65186_PASS2 :
|
||||
tps6518x_reg_write(REG_TPS65185_VCOM1, vcom_reg_val&0xff);
|
||||
tps6518x_reg_write(REG_TPS65185_VCOM2, (vcom_reg_val>>8)&0xff);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
static DEVICE_ATTR(temp_input, S_IRUGO, show_temp_input, NULL);
|
||||
static DEVICE_ATTR(intr_input, S_IRUGO, show_intr_regs, NULL);
|
||||
static DEVICE_ATTR(vcom_value, S_IWUSR | S_IRUGO, show_vcom, set_vcom);
|
||||
|
||||
static struct attribute *tps6518x_attributes[] = {
|
||||
&dev_attr_temp_input.attr,
|
||||
&dev_attr_intr_input.attr,
|
||||
&dev_attr_vcom_value.attr,
|
||||
NULL
|
||||
};
|
||||
|
||||
static const struct attribute_group tps6518x_group = {
|
||||
.attrs = tps6518x_attributes,
|
||||
};
|
||||
|
||||
/*
|
||||
* Real code
|
||||
*/
|
||||
static int tps6518x_sensor_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct tps6518x_data *data;
|
||||
int err;
|
||||
printk("tps6518x_sensor_probe starting\n");
|
||||
|
||||
data = kzalloc(sizeof(struct tps6518x_data), GFP_KERNEL);
|
||||
if (!data) {
|
||||
err = -ENOMEM;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* Register sysfs hooks */
|
||||
err = sysfs_create_group(&pdev->dev.kobj, &tps6518x_group);
|
||||
if (err)
|
||||
goto exit_free;
|
||||
|
||||
data->hwmon_dev = hwmon_device_register(&pdev->dev);
|
||||
if (IS_ERR(data->hwmon_dev)) {
|
||||
err = PTR_ERR(data->hwmon_dev);
|
||||
goto exit_remove_files;
|
||||
}
|
||||
|
||||
platform_set_drvdata(pdev, data);
|
||||
|
||||
printk("tps6518x_sensor_probe success\n");
|
||||
return 0;
|
||||
|
||||
exit_remove_files:
|
||||
sysfs_remove_group(&pdev->dev.kobj, &tps6518x_group);
|
||||
exit_free:
|
||||
kfree(data);
|
||||
exit:
|
||||
return err;
|
||||
}
|
||||
|
||||
static int tps6518x_sensor_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct tps6518x_data *data = platform_get_drvdata(pdev);
|
||||
|
||||
hwmon_device_unregister(data->hwmon_dev);
|
||||
sysfs_remove_group(&pdev->dev.kobj, &tps6518x_group);
|
||||
|
||||
kfree(data);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __init sensors_tps6518x_init(void)
|
||||
{
|
||||
return platform_driver_register(&tps6518x_sensor_driver);
|
||||
}
|
||||
module_init(sensors_tps6518x_init);
|
||||
|
||||
static void __exit sensors_tps6518x_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&tps6518x_sensor_driver);
|
||||
}
|
||||
module_exit(sensors_tps6518x_exit);
|
||||
|
||||
MODULE_DESCRIPTION("TPS6518x sensor driver");
|
||||
MODULE_LICENSE("GPL");
|
|
@ -590,6 +590,13 @@ config MFD_MAX17135
|
|||
This is the MAX17135 PMIC support. It includes
|
||||
core support for communication with the MAX17135 chip.
|
||||
|
||||
config MFD_TPS6518X
|
||||
tristate "Texas Instruments TPS6518X EPD PMIC core"
|
||||
depends on I2C
|
||||
help
|
||||
This is the TPS6518X PMIC support. It includes
|
||||
core support for communication with the TPS6518X chip.
|
||||
|
||||
config MFD_MAX77620
|
||||
bool "Maxim Semiconductor MAX77620 and MAX20024 PMIC Support"
|
||||
depends on I2C=y
|
||||
|
|
|
@ -81,6 +81,7 @@ obj-$(CONFIG_MFD_TPS65912) += tps65912-core.o
|
|||
obj-$(CONFIG_MFD_TPS65912_I2C) += tps65912-i2c.o
|
||||
obj-$(CONFIG_MFD_TPS65912_SPI) += tps65912-spi.o
|
||||
obj-$(CONFIG_MFD_TPS80031) += tps80031.o
|
||||
obj-$(CONFIG_MFD_TPS6518X) += tps6518x-core.o
|
||||
obj-$(CONFIG_MENELAUS) += menelaus.o
|
||||
|
||||
obj-$(CONFIG_TWL4030_CORE) += twl-core.o twl4030-irq.o twl6030-irq.o
|
||||
|
|
|
@ -0,0 +1,299 @@
|
|||
/*
|
||||
* Copyright (C) 2010 Freescale Semiconductor, Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
/*!
|
||||
* @file pmic/core/tps6518x.c
|
||||
* @brief This file contains TPS6518x specific PMIC code. This implementaion
|
||||
* may differ for each PMIC chip.
|
||||
*
|
||||
* @ingroup PMIC_CORE
|
||||
*/
|
||||
|
||||
/*
|
||||
* Includes
|
||||
*/
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/of_gpio.h>
|
||||
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/regulator/machine.h>
|
||||
#include <linux/pmic_status.h>
|
||||
#include <linux/mfd/core.h>
|
||||
#include <linux/mfd/tps6518x.h>
|
||||
#include <asm/mach-types.h>
|
||||
|
||||
static int tps6518x_detect(struct i2c_client *client, struct i2c_board_info *info);
|
||||
struct i2c_client *tps6518x_client;
|
||||
static struct regulator *gpio_regulator;
|
||||
|
||||
static struct mfd_cell tps6518x_devs[] = {
|
||||
{ .name = "tps6518x-pmic", },
|
||||
{ .name = "tps6518x-sns", },
|
||||
};
|
||||
|
||||
static const unsigned short normal_i2c[] = {EPDC_PMIC_I2C_ADDR, I2C_CLIENT_END};
|
||||
|
||||
int tps6518x_reg_read(int reg_num, unsigned int *reg_val)
|
||||
{
|
||||
int result;
|
||||
|
||||
if (tps6518x_client == NULL)
|
||||
return PMIC_ERROR;
|
||||
|
||||
result = i2c_smbus_read_byte_data(tps6518x_client, reg_num);
|
||||
if (result < 0) {
|
||||
dev_err(&tps6518x_client->dev,
|
||||
"Unable to read tps6518x register via I2C\n");
|
||||
return PMIC_ERROR;
|
||||
}
|
||||
|
||||
*reg_val = result;
|
||||
return PMIC_SUCCESS;
|
||||
}
|
||||
|
||||
int tps6518x_reg_write(int reg_num, const unsigned int reg_val)
|
||||
{
|
||||
int result;
|
||||
|
||||
if (tps6518x_client == NULL)
|
||||
return PMIC_ERROR;
|
||||
|
||||
result = i2c_smbus_write_byte_data(tps6518x_client, reg_num, reg_val);
|
||||
if (result < 0) {
|
||||
// dev_err(&tps6518x_client->dev,
|
||||
// "Unable to write TPS6518x register via I2C\n");
|
||||
return PMIC_ERROR;
|
||||
}
|
||||
|
||||
return PMIC_SUCCESS;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_OF
|
||||
static struct tps6518x_platform_data *tps6518x_i2c_parse_dt_pdata(
|
||||
struct device *dev)
|
||||
{
|
||||
struct tps6518x_platform_data *pdata;
|
||||
|
||||
pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
|
||||
if (!pdata) {
|
||||
dev_err(dev, "could not allocate memory for pdata\n");
|
||||
return ERR_PTR(-ENOMEM);
|
||||
}
|
||||
|
||||
return pdata;
|
||||
}
|
||||
#else
|
||||
static struct tps6518x_platform_data *tps6518x_i2c_parse_dt_pdata(
|
||||
struct device *dev)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
#endif /* !CONFIG_OF */
|
||||
|
||||
static int tps6518x_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
struct tps6518x *tps6518x;
|
||||
struct tps6518x_platform_data *pdata = client->dev.platform_data;
|
||||
struct device_node *np = client->dev.of_node;
|
||||
int ret = 0;
|
||||
|
||||
printk("tps6518x_probe calling\n");
|
||||
|
||||
if (!np)
|
||||
return -ENODEV;
|
||||
|
||||
gpio_regulator = devm_regulator_get(&client->dev, "SENSOR");
|
||||
if (!IS_ERR(gpio_regulator)) {
|
||||
ret = regulator_enable(gpio_regulator);
|
||||
if (ret) {
|
||||
dev_err(&client->dev, "gpio set voltage error\n");
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Create the PMIC data structure */
|
||||
tps6518x = kzalloc(sizeof(struct tps6518x), GFP_KERNEL);
|
||||
if (tps6518x == NULL) {
|
||||
kfree(client);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/* Initialize the PMIC data structure */
|
||||
i2c_set_clientdata(client, tps6518x);
|
||||
tps6518x->dev = &client->dev;
|
||||
tps6518x->i2c_client = client;
|
||||
|
||||
tps6518x_client = client;
|
||||
ret = tps6518x_detect(client, NULL);
|
||||
if (ret)
|
||||
goto err1;
|
||||
|
||||
mfd_add_devices(tps6518x->dev, -1, tps6518x_devs,
|
||||
ARRAY_SIZE(tps6518x_devs),
|
||||
NULL, 0, NULL);
|
||||
|
||||
if (tps6518x->dev->of_node) {
|
||||
pdata = tps6518x_i2c_parse_dt_pdata(tps6518x->dev);
|
||||
if (IS_ERR(pdata)) {
|
||||
ret = PTR_ERR(pdata);
|
||||
goto err2;
|
||||
}
|
||||
|
||||
}
|
||||
tps6518x->pdata = pdata;
|
||||
|
||||
dev_info(&client->dev, "PMIC TPS6518x for eInk display\n");
|
||||
|
||||
printk("tps6518x_probe success\n");
|
||||
|
||||
return ret;
|
||||
|
||||
err2:
|
||||
mfd_remove_devices(tps6518x->dev);
|
||||
err1:
|
||||
kfree(tps6518x);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static int tps6518x_remove(struct i2c_client *i2c)
|
||||
{
|
||||
struct tps6518x *tps6518x = i2c_get_clientdata(i2c);
|
||||
|
||||
mfd_remove_devices(tps6518x->dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tps6518x_suspend(struct i2c_client *client, pm_message_t state)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tps6518x_resume(struct i2c_client *client)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Return 0 if detection is successful, -ENODEV otherwise */
|
||||
static int tps6518x_detect(struct i2c_client *client,
|
||||
struct i2c_board_info *info)
|
||||
{
|
||||
//struct tps6518x_platform_data *pdata = client->dev.platform_data;
|
||||
struct i2c_adapter *adapter = client->adapter;
|
||||
u8 revId;
|
||||
printk("tps6518x_detect calling\n");
|
||||
|
||||
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
|
||||
return -ENODEV;
|
||||
|
||||
/* identification */
|
||||
revId = i2c_smbus_read_byte_data(client,
|
||||
REG_TPS6518x_REVID);
|
||||
|
||||
/*
|
||||
* Known rev-ids
|
||||
* tps165180 pass 1 = 0x50, tps65180 pass2 = 0x60, tps65181 pass1 = 0x51, tps65181 pass2 = 0x61,
|
||||
* tps65182,
|
||||
* tps65185 pass0 = 0x45, tps65186 pass0 0x46, tps65185 pass1 = 0x55, tps65186 pass1 0x56, tps65185 pass2 = 0x65, tps65186 pass2 0x66
|
||||
*/
|
||||
if (!((revId == TPS65180_PASS1) ||
|
||||
(revId == TPS65181_PASS1) ||
|
||||
(revId == TPS65180_PASS2) ||
|
||||
(revId == TPS65181_PASS2) ||
|
||||
(revId == TPS65185_PASS0) ||
|
||||
(revId == TPS65186_PASS0) ||
|
||||
(revId == TPS65185_PASS1) ||
|
||||
(revId == TPS65186_PASS1) ||
|
||||
(revId == TPS65185_PASS2) ||
|
||||
(revId == TPS65186_PASS2)))
|
||||
{
|
||||
dev_info(&adapter->dev,
|
||||
"Unsupported chip (Revision ID=0x%02X).\n", revId);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (info) {
|
||||
strlcpy(info->type, "tps6518x_sensor", I2C_NAME_SIZE);
|
||||
}
|
||||
printk("tps6518x_detect success\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct i2c_device_id tps6518x_id[] = {
|
||||
{ "tps6518x", 0 },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, tps6518x_id);
|
||||
|
||||
static const struct of_device_id tps6518x_dt_ids[] = {
|
||||
{
|
||||
.compatible = "ti,tps6518x",
|
||||
.data = (void *) &tps6518x_id[0],
|
||||
}, {
|
||||
/* sentinel */
|
||||
}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, tps6518x_dt_ids);
|
||||
|
||||
|
||||
static struct i2c_driver tps6518x_driver = {
|
||||
.driver = {
|
||||
.name = "tps6518x",
|
||||
.owner = THIS_MODULE,
|
||||
.of_match_table = tps6518x_dt_ids,
|
||||
},
|
||||
.probe = tps6518x_probe,
|
||||
.remove = tps6518x_remove,
|
||||
.suspend = tps6518x_suspend,
|
||||
.resume = tps6518x_resume,
|
||||
.id_table = tps6518x_id,
|
||||
.detect = tps6518x_detect,
|
||||
.address_list = &normal_i2c[0],
|
||||
};
|
||||
|
||||
static int __init tps6518x_init(void)
|
||||
{
|
||||
return i2c_add_driver(&tps6518x_driver);
|
||||
}
|
||||
|
||||
static void __exit tps6518x_exit(void)
|
||||
{
|
||||
i2c_del_driver(&tps6518x_driver);
|
||||
}
|
||||
|
||||
/*
|
||||
* Module entry points
|
||||
*/
|
||||
subsys_initcall(tps6518x_init);
|
||||
module_exit(tps6518x_exit);
|
|
@ -390,6 +390,10 @@ config REGULATOR_MAX77620
|
|||
chip to control Step-Down DC-DC and LDOs. Say Y here to
|
||||
enable the regulator driver.
|
||||
|
||||
config REGULATOR_TPS6518X
|
||||
tristate "Texas Instruments TPS6518X Regulator Support"
|
||||
depends on MFD_TPS6518X
|
||||
|
||||
config REGULATOR_MAX8649
|
||||
tristate "Maxim 8649 voltage regulator"
|
||||
depends on I2C
|
||||
|
|
|
@ -52,6 +52,7 @@ obj-$(CONFIG_REGULATOR_MAX14577) += max14577-regulator.o
|
|||
obj-$(CONFIG_REGULATOR_MAX1586) += max1586.o
|
||||
obj-$(CONFIG_REGULATOR_MAX17135) += max17135-regulator.o
|
||||
obj-$(CONFIG_REGULATOR_MAX77620) += max77620-regulator.o
|
||||
obj-$(CONFIG_REGULATOR_TPS6518X) += tps6518x-regulator.o
|
||||
obj-$(CONFIG_REGULATOR_MAX8649) += max8649.o
|
||||
obj-$(CONFIG_REGULATOR_MAX8660) += max8660.o
|
||||
obj-$(CONFIG_REGULATOR_MAX8907) += max8907-regulator.o
|
||||
|
|
|
@ -0,0 +1,810 @@
|
|||
/*
|
||||
* Copyright (C) 2010 Freescale Semiconductor, Inc. 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 as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
|
||||
* 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.
|
||||
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/regulator/machine.h>
|
||||
#include <linux/regulator/driver.h>
|
||||
#include <linux/regulator/of_regulator.h>
|
||||
#include <linux/mfd/tps6518x.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/pmic_status.h>
|
||||
#include <linux/of_gpio.h>
|
||||
|
||||
struct tps6518x_data {
|
||||
int num_regulators;
|
||||
struct tps6518x *tps6518x;
|
||||
struct regulator_dev **rdev;
|
||||
};
|
||||
|
||||
|
||||
static int tps6518x_pass_num = { 2 };
|
||||
static int tps6518x_vcom = { -2680000 };
|
||||
static int tps65180_current_Enable_Register = 0;
|
||||
|
||||
static int tps6518x_is_power_good(struct tps6518x *tps6518x);
|
||||
/*
|
||||
* to_reg_val(): Creates a register value with new data
|
||||
*
|
||||
* Creates a new register value for a particular field. The data
|
||||
* outside of the new field is not modified.
|
||||
*
|
||||
* @cur_reg: current value in register
|
||||
* @reg_mask: mask of field bits to be modified
|
||||
* @fld_val: new value for register field.
|
||||
*/
|
||||
static unsigned int to_reg_val(unsigned int cur_reg, unsigned int fld_mask,
|
||||
unsigned int fld_val)
|
||||
{
|
||||
return (cur_reg & (~fld_mask)) | fld_val;
|
||||
}
|
||||
|
||||
/*
|
||||
* Regulator operations
|
||||
*/
|
||||
/* Convert uV to the VCOM register bitfield setting */
|
||||
|
||||
static int vcom_rs_to_uV(unsigned int reg_setting)
|
||||
{
|
||||
if (reg_setting <= TPS65180_VCOM_MIN_SET)
|
||||
return TPS65180_VCOM_MIN_uV;
|
||||
if (reg_setting >= TPS65180_VCOM_MAX_SET)
|
||||
return TPS65180_VCOM_MAX_uV;
|
||||
return -(reg_setting * TPS65180_VCOM_STEP_uV);
|
||||
}
|
||||
static int vcom2_rs_to_uV(unsigned int reg_setting)
|
||||
{
|
||||
if (reg_setting <= TPS65185_VCOM_MIN_SET)
|
||||
return TPS65185_VCOM_MIN_uV;
|
||||
if (reg_setting >= TPS65185_VCOM_MAX_SET)
|
||||
return TPS65185_VCOM_MAX_uV;
|
||||
return -(reg_setting * TPS65185_VCOM_STEP_uV);
|
||||
}
|
||||
|
||||
|
||||
static int vcom_uV_to_rs(int uV)
|
||||
{
|
||||
if (uV <= TPS65180_VCOM_MIN_uV)
|
||||
return TPS65180_VCOM_MIN_SET;
|
||||
if (uV >= TPS65180_VCOM_MAX_uV)
|
||||
return TPS65180_VCOM_MAX_SET;
|
||||
return (-uV) / TPS65180_VCOM_STEP_uV;
|
||||
}
|
||||
|
||||
static int vcom2_uV_to_rs(int uV)
|
||||
{
|
||||
if (uV <= TPS65185_VCOM_MIN_uV)
|
||||
return TPS65185_VCOM_MIN_SET;
|
||||
if (uV >= TPS65185_VCOM_MAX_uV)
|
||||
return TPS65185_VCOM_MAX_SET;
|
||||
return (-uV) / TPS65185_VCOM_STEP_uV;
|
||||
}
|
||||
|
||||
static int epdc_pwr0_enable(struct regulator_dev *reg)
|
||||
{
|
||||
struct tps6518x *tps6518x = rdev_get_drvdata(reg);
|
||||
|
||||
gpio_set_value(tps6518x->gpio_pmic_powerup, 1);
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
static int epdc_pwr0_disable(struct regulator_dev *reg)
|
||||
{
|
||||
struct tps6518x *tps6518x = rdev_get_drvdata(reg);
|
||||
|
||||
gpio_set_value(tps6518x->gpio_pmic_powerup, 0);
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
static int tps6518x_v3p3_enable(struct regulator_dev *reg)
|
||||
{
|
||||
struct tps6518x *tps6518x = rdev_get_drvdata(reg);
|
||||
|
||||
gpio_set_value(tps6518x->gpio_pmic_powerup, 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tps6518x_v3p3_disable(struct regulator_dev *reg)
|
||||
{
|
||||
struct tps6518x *tps6518x = rdev_get_drvdata(reg);
|
||||
|
||||
gpio_set_value(tps6518x->gpio_pmic_powerup, 0);
|
||||
return 0;
|
||||
|
||||
}
|
||||
static int tps6518x_v3p3_is_enabled(struct regulator_dev *reg)
|
||||
{
|
||||
struct tps6518x *tps6518x = rdev_get_drvdata(reg);
|
||||
int gpio = gpio_get_value(tps6518x->gpio_pmic_powerup);
|
||||
|
||||
if (gpio == 0)
|
||||
return 0;
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int tps6518x_vcom_set_voltage(struct regulator_dev *reg,
|
||||
int minuV, int uV, unsigned *selector)
|
||||
{
|
||||
struct tps6518x *tps6518x = rdev_get_drvdata(reg);
|
||||
unsigned int cur_reg_val; /* current register value to modify */
|
||||
unsigned int new_reg_val; /* new register value to write */
|
||||
int retval;
|
||||
|
||||
/*
|
||||
* this will not work on tps65182
|
||||
*/
|
||||
if (tps6518x->revID == 65182)
|
||||
return 0;
|
||||
|
||||
#if 0
|
||||
if (uV < 200000)
|
||||
return 0;
|
||||
#endif
|
||||
|
||||
switch (tps6518x->revID & 15)
|
||||
{
|
||||
case 0 : /* TPS65180 */
|
||||
case 1 : /* TPS65181 */
|
||||
case 4 : /* TPS65180-rev1 */
|
||||
tps6518x_reg_read(REG_TPS65180_VCOM_ADJUST,&cur_reg_val);
|
||||
new_reg_val = to_reg_val(cur_reg_val,
|
||||
BITFMASK(VCOM_SET),
|
||||
BITFVAL(VCOM_SET, vcom_uV_to_rs(uV)));
|
||||
|
||||
retval = tps6518x_reg_write(REG_TPS65180_VCOM_ADJUST,
|
||||
new_reg_val);
|
||||
break;
|
||||
case 5 : /* TPS65185 */
|
||||
case 6 : /* TPS65186 */
|
||||
gpio_set_value(tps6518x->gpio_pmic_wakeup,1);
|
||||
retval = tps6518x_reg_write(REG_TPS65185_VCOM1,
|
||||
vcom2_uV_to_rs(uV) & 255);
|
||||
tps6518x_reg_read( REG_TPS65185_VCOM2,&cur_reg_val);
|
||||
new_reg_val = to_reg_val(cur_reg_val,
|
||||
BITFMASK(VCOM2_SET),
|
||||
BITFVAL(VCOM2_SET, vcom2_uV_to_rs(uV)/256));
|
||||
|
||||
retval = tps6518x_reg_write(REG_TPS65185_VCOM2,
|
||||
new_reg_val);
|
||||
|
||||
break;
|
||||
default :
|
||||
retval = -1;
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
static int tps6518x_vcom_get_voltage(struct regulator_dev *reg)
|
||||
{
|
||||
struct tps6518x *tps6518x = rdev_get_drvdata(reg);
|
||||
unsigned int cur_reg_val; /* current register value */
|
||||
unsigned int cur_reg2_val; /* current register value */
|
||||
unsigned int cur_fld_val; /* current bitfield value*/
|
||||
int vcomValue;
|
||||
|
||||
/*
|
||||
* this will not work on tps65182
|
||||
*/
|
||||
if (tps6518x->revID == 65182)
|
||||
return 0;
|
||||
|
||||
switch (tps6518x->revID & 15)
|
||||
{
|
||||
case 0 : /* TPS65180 */
|
||||
case 1 : /* TPS65181 */
|
||||
case 4 : /* TPS65180-rev1 */
|
||||
tps6518x_reg_read(REG_TPS65180_VCOM_ADJUST, &cur_reg_val);
|
||||
cur_fld_val = BITFEXT(cur_reg_val, VCOM_SET);
|
||||
vcomValue = vcom_rs_to_uV(cur_fld_val);
|
||||
break;
|
||||
case 5 : /* TPS65185 */
|
||||
case 6 : /* TPS65186 */
|
||||
tps6518x_reg_read(REG_TPS65185_VCOM1,&cur_reg_val);
|
||||
tps6518x_reg_read(REG_TPS65185_VCOM2,&cur_reg2_val);
|
||||
cur_reg_val |= 256 * (1 & cur_reg2_val);
|
||||
vcomValue = vcom2_rs_to_uV(cur_reg_val);
|
||||
break;
|
||||
default:
|
||||
vcomValue = 0;
|
||||
}
|
||||
|
||||
return vcomValue;
|
||||
|
||||
}
|
||||
|
||||
static int tps6518x_vcom_enable(struct regulator_dev *reg)
|
||||
{
|
||||
struct tps6518x *tps6518x = rdev_get_drvdata(reg);
|
||||
unsigned int cur_reg_val; /* current register value */
|
||||
int vcomEnable = 0;
|
||||
/*
|
||||
* check for the TPS65182 device
|
||||
*/
|
||||
if (tps6518x->revID == 65182)
|
||||
{
|
||||
gpio_set_value(tps6518x->gpio_pmic_vcom_ctrl,vcomEnable);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check to see if we need to set the VCOM voltage.
|
||||
* Should only be done one time. And, we can
|
||||
* only change vcom voltage if we have been enabled.
|
||||
*/
|
||||
if (!tps6518x->vcom_setup && tps6518x_is_power_good(tps6518x)) {
|
||||
tps6518x_vcom_set_voltage(reg,
|
||||
tps6518x->vcom_uV,
|
||||
tps6518x->vcom_uV,
|
||||
NULL);
|
||||
tps6518x->vcom_setup = true;
|
||||
}
|
||||
|
||||
switch (tps6518x->revID & 15)
|
||||
{
|
||||
case 0 : /* TPS65180 */
|
||||
case 1 : /* TPS65181 */
|
||||
case 4 : /* TPS65180-rev1 */
|
||||
vcomEnable = 1;
|
||||
break;
|
||||
case 5 : /* TPS65185 */
|
||||
case 6 : /* TPS65186 */
|
||||
tps6518x_reg_read(REG_TPS65185_VCOM2,&cur_reg_val);
|
||||
// do not enable vcom if HiZ bit is set
|
||||
if (cur_reg_val & (1<<VCOM_HiZ_LSH))
|
||||
vcomEnable = 0;
|
||||
else
|
||||
vcomEnable = 1;
|
||||
break;
|
||||
default:
|
||||
vcomEnable = 0;
|
||||
}
|
||||
gpio_set_value(tps6518x->gpio_pmic_vcom_ctrl,vcomEnable);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tps6518x_vcom_disable(struct regulator_dev *reg)
|
||||
{
|
||||
struct tps6518x *tps6518x = rdev_get_drvdata(reg);
|
||||
|
||||
gpio_set_value(tps6518x->gpio_pmic_vcom_ctrl,0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tps6518x_vcom_is_enabled(struct regulator_dev *reg)
|
||||
{
|
||||
struct tps6518x *tps6518x = rdev_get_drvdata(reg);
|
||||
|
||||
int gpio = gpio_get_value(tps6518x->gpio_pmic_vcom_ctrl);
|
||||
if (gpio == 0)
|
||||
return 0;
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int tps6518x_is_power_good(struct tps6518x *tps6518x)
|
||||
{
|
||||
/*
|
||||
* XOR of polarity (starting value) and current
|
||||
* value yields whether power is good.
|
||||
*/
|
||||
return gpio_get_value(tps6518x->gpio_pmic_pwrgood) ^
|
||||
tps6518x->pwrgood_polarity;
|
||||
}
|
||||
|
||||
static int tps6518x_wait_power_good(struct tps6518x *tps6518x)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < tps6518x->max_wait * 3; i++) {
|
||||
if (tps6518x_is_power_good(tps6518x))
|
||||
return 0;
|
||||
|
||||
msleep(1);
|
||||
}
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
static int tps6518x_display_enable(struct regulator_dev *reg)
|
||||
{
|
||||
struct tps6518x *tps6518x = rdev_get_drvdata(reg);
|
||||
unsigned int cur_reg_val; /* current register value to modify */
|
||||
unsigned int fld_mask; /* register mask for bitfield to modify */
|
||||
unsigned int fld_val; /* new bitfield value to write */
|
||||
unsigned int new_reg_val; /* new register value to write */
|
||||
if (tps6518x->revID == 65182)
|
||||
{
|
||||
epdc_pwr0_enable(reg);
|
||||
}
|
||||
else
|
||||
{
|
||||
gpio_set_value(tps6518x->gpio_pmic_wakeup,1);
|
||||
|
||||
/* enable display regulators */
|
||||
cur_reg_val = tps65180_current_Enable_Register & 0x3f;
|
||||
fld_mask = BITFMASK(VDDH_EN) | BITFMASK(VPOS_EN) |
|
||||
BITFMASK(VEE_EN) | BITFMASK(VNEG_EN);
|
||||
fld_val = BITFVAL(VDDH_EN, true) | BITFVAL(VPOS_EN, true) |
|
||||
BITFVAL(VEE_EN, true) | BITFVAL(VNEG_EN, true) | BITFVAL(VCOM_EN, true);
|
||||
new_reg_val = tps65180_current_Enable_Register = to_reg_val(cur_reg_val, fld_mask, fld_val);
|
||||
tps6518x_reg_write(REG_TPS65180_ENABLE, new_reg_val);
|
||||
|
||||
/* turn on display regulators */
|
||||
cur_reg_val = tps65180_current_Enable_Register & 0x3f;
|
||||
fld_mask = BITFMASK(ACTIVE);
|
||||
fld_val = BITFVAL(ACTIVE, true);
|
||||
new_reg_val = tps65180_current_Enable_Register = to_reg_val(cur_reg_val, fld_mask, fld_val);
|
||||
tps6518x_reg_write(REG_TPS65180_ENABLE, new_reg_val);
|
||||
}
|
||||
|
||||
return tps6518x_wait_power_good(tps6518x);
|
||||
}
|
||||
|
||||
static int tps6518x_display_disable(struct regulator_dev *reg)
|
||||
{
|
||||
struct tps6518x *tps6518x = rdev_get_drvdata(reg);
|
||||
unsigned int cur_reg_val; /* current register value to modify */
|
||||
unsigned int fld_mask; /* register mask for bitfield to modify */
|
||||
unsigned int fld_val; /* new bitfield value to write */
|
||||
unsigned int new_reg_val; /* new register value to write */
|
||||
|
||||
if (tps6518x->revID == 65182)
|
||||
{
|
||||
epdc_pwr0_disable(reg);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* turn off display regulators */
|
||||
cur_reg_val = tps65180_current_Enable_Register & 0x3f;
|
||||
fld_mask = BITFMASK(VCOM_EN) | BITFMASK(STANDBY);
|
||||
fld_val = BITFVAL(VCOM_EN, true) | BITFVAL(STANDBY, true);
|
||||
new_reg_val = tps65180_current_Enable_Register = to_reg_val(cur_reg_val, fld_mask, fld_val);
|
||||
tps6518x_reg_write(REG_TPS65180_ENABLE, new_reg_val);
|
||||
|
||||
}
|
||||
|
||||
msleep(tps6518x->max_wait);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tps6518x_display_is_enabled(struct regulator_dev *reg)
|
||||
{
|
||||
struct tps6518x *tps6518x = rdev_get_drvdata(reg);
|
||||
|
||||
if (tps6518x->revID == 65182)
|
||||
return gpio_get_value(tps6518x->gpio_pmic_wakeup) ? 1:0;
|
||||
else
|
||||
return tps65180_current_Enable_Register & BITFMASK(ACTIVE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Regulator operations
|
||||
*/
|
||||
|
||||
static struct regulator_ops tps6518x_display_ops = {
|
||||
.enable = tps6518x_display_enable,
|
||||
.disable = tps6518x_display_disable,
|
||||
.is_enabled = tps6518x_display_is_enabled,
|
||||
};
|
||||
|
||||
static struct regulator_ops tps6518x_vcom_ops = {
|
||||
.enable = tps6518x_vcom_enable,
|
||||
.disable = tps6518x_vcom_disable,
|
||||
.get_voltage = tps6518x_vcom_get_voltage,
|
||||
.set_voltage = tps6518x_vcom_set_voltage,
|
||||
.is_enabled = tps6518x_vcom_is_enabled,
|
||||
};
|
||||
|
||||
static struct regulator_ops tps6518x_v3p3_ops = {
|
||||
.enable = tps6518x_v3p3_enable,
|
||||
.disable = tps6518x_v3p3_disable,
|
||||
.is_enabled = tps6518x_v3p3_is_enabled,
|
||||
};
|
||||
|
||||
/*
|
||||
* Regulator descriptors
|
||||
*/
|
||||
static struct regulator_desc tps6518x_reg[TPS6518x_NUM_REGULATORS] = {
|
||||
{
|
||||
.name = "DISPLAY",
|
||||
.id = TPS6518x_DISPLAY,
|
||||
.ops = &tps6518x_display_ops,
|
||||
.type = REGULATOR_VOLTAGE,
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
{
|
||||
.name = "VCOM",
|
||||
.id = TPS6518x_VCOM,
|
||||
.ops = &tps6518x_vcom_ops,
|
||||
.type = REGULATOR_VOLTAGE,
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
{
|
||||
.name = "V3P3",
|
||||
.id = TPS6518x_V3P3,
|
||||
.ops = &tps6518x_v3p3_ops,
|
||||
.type = REGULATOR_VOLTAGE,
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
};
|
||||
|
||||
static void tps6518x_setup_timings(struct tps6518x *tps6518x)
|
||||
{
|
||||
|
||||
int temp0, temp1, temp2, temp3;
|
||||
|
||||
/* read the current setting in the PMIC */
|
||||
if ((tps6518x->revID == TPS65180_PASS1) || (tps6518x->revID == TPS65181_PASS1) ||
|
||||
(tps6518x->revID == TPS65180_PASS2) || (tps6518x->revID == TPS65181_PASS2)) {
|
||||
tps6518x_reg_read(REG_TPS65180_PWRSEQ0, &temp0);
|
||||
tps6518x_reg_read(REG_TPS65180_PWRSEQ1, &temp1);
|
||||
tps6518x_reg_read(REG_TPS65180_PWRSEQ2, &temp2);
|
||||
|
||||
if ((temp0 != tps6518x->pwr_seq0) ||
|
||||
(temp1 != tps6518x->pwr_seq1) ||
|
||||
(temp2 != tps6518x->pwr_seq2)) {
|
||||
tps6518x_reg_write(REG_TPS65180_PWRSEQ0, tps6518x->pwr_seq0);
|
||||
tps6518x_reg_write(REG_TPS65180_PWRSEQ1, tps6518x->pwr_seq1);
|
||||
tps6518x_reg_write(REG_TPS65180_PWRSEQ2, tps6518x->pwr_seq2);
|
||||
}
|
||||
}
|
||||
|
||||
if ((tps6518x->revID == TPS65185_PASS0) ||
|
||||
(tps6518x->revID == TPS65186_PASS0) ||
|
||||
(tps6518x->revID == TPS65185_PASS1) ||
|
||||
(tps6518x->revID == TPS65186_PASS1) ||
|
||||
(tps6518x->revID == TPS65185_PASS2) ||
|
||||
(tps6518x->revID == TPS65186_PASS2)) {
|
||||
tps6518x_reg_read(REG_TPS65185_UPSEQ0, &temp0);
|
||||
tps6518x_reg_read(REG_TPS65185_UPSEQ1, &temp1);
|
||||
tps6518x_reg_read(REG_TPS65185_DWNSEQ0, &temp2);
|
||||
tps6518x_reg_read(REG_TPS65185_DWNSEQ1, &temp3);
|
||||
if ((temp0 != tps6518x->upseq0) ||
|
||||
(temp1 != tps6518x->upseq1) ||
|
||||
(temp2 != tps6518x->dwnseq0) ||
|
||||
(temp3 != tps6518x->dwnseq1)) {
|
||||
tps6518x_reg_write(REG_TPS65185_UPSEQ0, tps6518x->upseq0);
|
||||
tps6518x_reg_write(REG_TPS65185_UPSEQ1, tps6518x->upseq1);
|
||||
tps6518x_reg_write(REG_TPS65185_DWNSEQ0, tps6518x->dwnseq0);
|
||||
tps6518x_reg_write(REG_TPS65185_DWNSEQ1, tps6518x->dwnseq1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#define CHECK_PROPERTY_ERROR_KFREE(prop) \
|
||||
do { \
|
||||
int ret = of_property_read_u32(tps6518x->dev->of_node, \
|
||||
#prop, &tps6518x->prop); \
|
||||
if (ret < 0) { \
|
||||
return ret; \
|
||||
} \
|
||||
} while (0);
|
||||
|
||||
#ifdef CONFIG_OF
|
||||
static int tps6518x_pmic_dt_parse_pdata(struct platform_device *pdev,
|
||||
struct tps6518x_platform_data *pdata)
|
||||
{
|
||||
struct tps6518x *tps6518x = dev_get_drvdata(pdev->dev.parent);
|
||||
struct device_node *pmic_np, *regulators_np, *reg_np;
|
||||
struct tps6518x_regulator_data *rdata;
|
||||
int i, ret;
|
||||
|
||||
pmic_np = of_node_get(tps6518x->dev->of_node);
|
||||
if (!pmic_np) {
|
||||
dev_err(&pdev->dev, "could not find pmic sub-node\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
regulators_np = of_find_node_by_name(pmic_np, "regulators");
|
||||
if (!regulators_np) {
|
||||
dev_err(&pdev->dev, "could not find regulators sub-node\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
pdata->num_regulators = of_get_child_count(regulators_np);
|
||||
dev_dbg(&pdev->dev, "num_regulators %d\n", pdata->num_regulators);
|
||||
|
||||
rdata = devm_kzalloc(&pdev->dev, sizeof(*rdata) *
|
||||
pdata->num_regulators, GFP_KERNEL);
|
||||
if (!rdata) {
|
||||
of_node_put(regulators_np);
|
||||
dev_err(&pdev->dev, "could not allocate memory for"
|
||||
"regulator data\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
pdata->regulators = rdata;
|
||||
for_each_child_of_node(regulators_np, reg_np) {
|
||||
for (i = 0; i < ARRAY_SIZE(tps6518x_reg); i++)
|
||||
if (!of_node_cmp(reg_np->name, tps6518x_reg[i].name))
|
||||
break;
|
||||
|
||||
if (i == ARRAY_SIZE(tps6518x_reg)) {
|
||||
dev_warn(&pdev->dev, "don't know how to configure"
|
||||
"regulator %s\n", reg_np->name);
|
||||
continue;
|
||||
}
|
||||
|
||||
rdata->id = i;
|
||||
rdata->initdata = of_get_regulator_init_data(&pdev->dev,
|
||||
reg_np);
|
||||
rdata->reg_node = reg_np;
|
||||
rdata++;
|
||||
}
|
||||
of_node_put(regulators_np);
|
||||
|
||||
tps6518x->max_wait = (6 + 6 + 6 + 6);
|
||||
|
||||
tps6518x->gpio_pmic_wakeup = of_get_named_gpio(pmic_np,
|
||||
"gpio_pmic_wakeup", 0);
|
||||
if (!gpio_is_valid(tps6518x->gpio_pmic_wakeup)) {
|
||||
dev_err(&pdev->dev, "no epdc pmic wakeup pin available\n");
|
||||
goto err;
|
||||
}
|
||||
ret = devm_gpio_request_one(&pdev->dev, tps6518x->gpio_pmic_wakeup,
|
||||
GPIOF_OUT_INIT_LOW, "epdc-pmic-wake");
|
||||
if (ret < 0)
|
||||
goto err;
|
||||
|
||||
tps6518x->gpio_pmic_vcom_ctrl = of_get_named_gpio(pmic_np,
|
||||
"gpio_pmic_vcom_ctrl", 0);
|
||||
if (!gpio_is_valid(tps6518x->gpio_pmic_vcom_ctrl)) {
|
||||
dev_err(&pdev->dev, "no epdc pmic vcom_ctrl pin available\n");
|
||||
goto err;
|
||||
}
|
||||
ret = devm_gpio_request_one(&pdev->dev, tps6518x->gpio_pmic_vcom_ctrl,
|
||||
GPIOF_OUT_INIT_LOW, "epdc-vcom");
|
||||
if (ret < 0)
|
||||
goto err;
|
||||
|
||||
tps6518x->gpio_pmic_powerup = of_get_named_gpio(pmic_np,
|
||||
"gpio_pmic_powerup", 0);
|
||||
if (!gpio_is_valid(tps6518x->gpio_pmic_powerup)) {
|
||||
dev_err(&pdev->dev, "no epdc pmic powerup pin available\n");
|
||||
goto err;
|
||||
}
|
||||
ret = devm_gpio_request_one(&pdev->dev, tps6518x->gpio_pmic_powerup,
|
||||
GPIOF_OUT_INIT_LOW, "epdc-powerup");
|
||||
if (ret < 0)
|
||||
goto err;
|
||||
|
||||
tps6518x->gpio_pmic_intr = of_get_named_gpio(pmic_np,
|
||||
"gpio_pmic_intr", 0);
|
||||
if (!gpio_is_valid(tps6518x->gpio_pmic_intr)) {
|
||||
dev_err(&pdev->dev, "no epdc pmic intr pin available\n");
|
||||
goto err;
|
||||
}
|
||||
ret = devm_gpio_request_one(&pdev->dev, tps6518x->gpio_pmic_intr,
|
||||
GPIOF_IN, "epdc-pmic-int");
|
||||
if (ret < 0)
|
||||
goto err;
|
||||
|
||||
tps6518x->gpio_pmic_pwrgood = of_get_named_gpio(pmic_np,
|
||||
"gpio_pmic_pwrgood", 0);
|
||||
if (!gpio_is_valid(tps6518x->gpio_pmic_pwrgood)) {
|
||||
dev_err(&pdev->dev, "no epdc pmic pwrgood pin available\n");
|
||||
goto err;
|
||||
}
|
||||
ret = devm_gpio_request_one(&pdev->dev, tps6518x->gpio_pmic_pwrgood,
|
||||
GPIOF_IN, "epdc-pwrstat");
|
||||
if (ret < 0)
|
||||
goto err;
|
||||
|
||||
err:
|
||||
return 0;
|
||||
|
||||
}
|
||||
#else
|
||||
static int tps6518x_pmic_dt_parse_pdata(struct platform_device *pdev,
|
||||
struct tps6518x *tps6518x)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif /* !CONFIG_OF */
|
||||
|
||||
/*
|
||||
* Regulator init/probing/exit functions
|
||||
*/
|
||||
static int tps6518x_regulator_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct tps6518x *tps6518x = dev_get_drvdata(pdev->dev.parent);
|
||||
struct tps6518x_platform_data *pdata = tps6518x->pdata;
|
||||
struct tps6518x_data *priv;
|
||||
struct regulator_dev **rdev;
|
||||
struct regulator_config config = { };
|
||||
int size, i, ret = 0;
|
||||
|
||||
printk("tps6518x_regulator_probe starting\n");
|
||||
|
||||
if (tps6518x->dev->of_node) {
|
||||
ret = tps6518x_pmic_dt_parse_pdata(pdev, pdata);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
priv = devm_kzalloc(&pdev->dev, sizeof(struct tps6518x_data),
|
||||
GFP_KERNEL);
|
||||
if (!priv)
|
||||
return -ENOMEM;
|
||||
|
||||
size = sizeof(struct regulator_dev *) * pdata->num_regulators;
|
||||
priv->rdev = devm_kzalloc(&pdev->dev, size, GFP_KERNEL);
|
||||
if (!priv->rdev)
|
||||
return -ENOMEM;
|
||||
|
||||
rdev = priv->rdev;
|
||||
priv->num_regulators = pdata->num_regulators;
|
||||
platform_set_drvdata(pdev, priv);
|
||||
|
||||
tps6518x->vcom_setup = false;
|
||||
tps6518x->pass_num = tps6518x_pass_num;
|
||||
tps6518x->vcom_uV = tps6518x_vcom;
|
||||
|
||||
for (i = 0; i < pdata->num_regulators; i++) {
|
||||
int id = pdata->regulators[i].id;
|
||||
|
||||
config.dev = tps6518x->dev;
|
||||
config.init_data = pdata->regulators[i].initdata;
|
||||
config.driver_data = tps6518x;
|
||||
config.of_node = pdata->regulators[i].reg_node;
|
||||
|
||||
rdev[i] = regulator_register(&tps6518x_reg[id], &config);
|
||||
if (IS_ERR(rdev[i])) {
|
||||
ret = PTR_ERR(rdev[i]);
|
||||
dev_err(&pdev->dev, "regulator init failed for %d\n",
|
||||
id);
|
||||
rdev[i] = NULL;
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Set up PMIC timing values.
|
||||
* Should only be done one time! Timing values may only be
|
||||
* changed a limited number of times according to spec.
|
||||
*/
|
||||
tps6518x_setup_timings(tps6518x);
|
||||
|
||||
printk("tps6518x_regulator_probe success\n");
|
||||
return 0;
|
||||
err:
|
||||
while (--i >= 0)
|
||||
regulator_unregister(rdev[i]);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int tps6518x_regulator_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct tps6518x_data *priv = platform_get_drvdata(pdev);
|
||||
struct regulator_dev **rdev = priv->rdev;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < priv->num_regulators; i++)
|
||||
regulator_unregister(rdev[i]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct platform_device_id tps6518x_pmic_id[] = {
|
||||
{ "tps6518x-pmic", 0},
|
||||
{ /* sentinel */ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(platform, tps6518x_pmic_id);
|
||||
|
||||
static struct platform_driver tps6518x_regulator_driver = {
|
||||
.probe = tps6518x_regulator_probe,
|
||||
.remove = tps6518x_regulator_remove,
|
||||
.id_table = tps6518x_pmic_id,
|
||||
.driver = {
|
||||
.name = "tps6518x-pmic",
|
||||
},
|
||||
};
|
||||
|
||||
static int __init tps6518x_regulator_init(void)
|
||||
{
|
||||
return platform_driver_register(&tps6518x_regulator_driver);
|
||||
}
|
||||
subsys_initcall_sync(tps6518x_regulator_init);
|
||||
|
||||
static void __exit tps6518x_regulator_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&tps6518x_regulator_driver);
|
||||
}
|
||||
module_exit(tps6518x_regulator_exit);
|
||||
|
||||
|
||||
/*
|
||||
* Parse user specified options (`tps6518x:')
|
||||
* example:
|
||||
* tps6518x:pass=2,vcom=-1250000
|
||||
*/
|
||||
static int __init tps6518x_setup(char *options)
|
||||
{
|
||||
int ret;
|
||||
char *opt;
|
||||
unsigned long ulResult;
|
||||
while ((opt = strsep(&options, ",")) != NULL) {
|
||||
if (!*opt)
|
||||
continue;
|
||||
if (!strncmp(opt, "pass=", 5)) {
|
||||
ret = strict_strtoul((const char *)(opt + 5), 0, &ulResult);
|
||||
tps6518x_pass_num = ulResult;
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
if (!strncmp(opt, "vcom=", 5)) {
|
||||
int offs = 5;
|
||||
if (opt[5] == '-')
|
||||
offs = 6;
|
||||
ret = strict_strtoul((const char *)(opt + offs), 0, &ulResult);
|
||||
tps6518x_vcom = (int) ulResult;
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
tps6518x_vcom = -tps6518x_vcom;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
__setup("tps6518x:", tps6518x_setup);
|
||||
|
||||
static int __init tps65182_setup(char *options)
|
||||
{
|
||||
int ret;
|
||||
char *opt;
|
||||
unsigned long ulResult;
|
||||
while ((opt = strsep(&options, ",")) != NULL) {
|
||||
if (!*opt)
|
||||
continue;
|
||||
if (!strncmp(opt, "pass=", 5)) {
|
||||
ret = strict_strtoul((const char *)(opt + 5), 0, &ulResult);
|
||||
tps6518x_pass_num = ulResult;
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
if (!strncmp(opt, "vcom=", 5)) {
|
||||
int offs = 5;
|
||||
if (opt[5] == '-')
|
||||
offs = 6;
|
||||
ret = strict_strtoul((const char *)(opt + offs), 0, &ulResult);
|
||||
tps6518x_vcom = (int) ulResult;
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
tps6518x_vcom = -tps6518x_vcom;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
__setup("tps65182:", tps65182_setup);
|
||||
|
||||
|
||||
/* Module information */
|
||||
MODULE_DESCRIPTION("TPS6518x regulator driver");
|
||||
MODULE_LICENSE("GPL");
|
|
@ -0,0 +1,357 @@
|
|||
/*
|
||||
* Copyright (C) 2010 Freescale Semiconductor, Inc. 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 as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
#ifndef __LINUX_REGULATOR_TPS6518x_H_
|
||||
#define __LINUX_REGULATOR_TPS6518x_H_
|
||||
|
||||
/*
|
||||
* EPDC PMIC I2C address
|
||||
* PAPYRUS II 1p1 and later uses 0x68, others 0x48
|
||||
*/
|
||||
#define EPDC_PMIC_I2C_ADDR 0x68
|
||||
|
||||
/*
|
||||
* currently supported rev IDs
|
||||
*/
|
||||
//#define TPS65180_PASS1 0x54
|
||||
//#define TPS65181_PASS1 0x55
|
||||
#define TPS65180_PASS1 0x50
|
||||
#define TPS65181_PASS1 0x51
|
||||
#define TPS65180_PASS2 0x60
|
||||
#define TPS65181_PASS2 0x61
|
||||
#define TPS65185_PASS0 0x45
|
||||
#define TPS65186_PASS0 0x46
|
||||
#define TPS65185_PASS1 0x55
|
||||
#define TPS65186_PASS1 0x56
|
||||
#define TPS65185_PASS2 0x65
|
||||
#define TPS65186_PASS2 0x66
|
||||
|
||||
/*
|
||||
* PMIC Register Addresses
|
||||
*/
|
||||
enum {
|
||||
REG_TPS6518x_TMST_VAL = 0x0,
|
||||
REG_TPS65185_ENABLE,
|
||||
REG_TPS65185_VADJ,
|
||||
REG_TPS65185_VCOM1,
|
||||
REG_TPS65185_VCOM2,
|
||||
REG_TPS65185_INT_EN1,
|
||||
REG_TPS65185_INT_EN2,
|
||||
REG_TPS65185_INT1,
|
||||
REG_TPS65185_INT2,
|
||||
REG_TPS65185_UPSEQ0,
|
||||
REG_TPS65185_UPSEQ1,
|
||||
REG_TPS65185_DWNSEQ0,
|
||||
REG_TPS65185_DWNSEQ1,
|
||||
REG_TPS65185_TMST1,
|
||||
REG_TPS65185_TMST2,
|
||||
REG_TPS6518x_PG,
|
||||
REG_TPS6518x_REVID,
|
||||
TPS6518x_REG_NUM,
|
||||
};
|
||||
|
||||
enum {
|
||||
REG_TPS65180_TMST_VAL = 0x0,
|
||||
REG_TPS65180_ENABLE,
|
||||
REG_TPS65180_VP_ADJUST,
|
||||
REG_TPS65180_VN_ADJUST,
|
||||
REG_TPS65180_VCOM_ADJUST,
|
||||
REG_TPS65180_INT_EN1,
|
||||
REG_TPS65180_INT_EN2,
|
||||
REG_TPS65180_INT1,
|
||||
REG_TPS65180_INT2,
|
||||
REG_TPS65180_PWRSEQ0,
|
||||
REG_TPS65180_PWRSEQ1,
|
||||
REG_TPS65180_PWRSEQ2,
|
||||
REG_TPS65180_TMST_CONFIG,
|
||||
REG_TPS65180_TMST_OS,
|
||||
REG_TPS65180_TMST_HYST,
|
||||
REG_TPS65180_PG_STATUS,
|
||||
REG_TPS65180_REVID,
|
||||
REG_TPS65180_FIX_READ_PTR,
|
||||
TPS65180_REG_NUM,
|
||||
};
|
||||
|
||||
#define TPS6518x_MAX_REGISTER 0xFF
|
||||
|
||||
/*
|
||||
* Bitfield macros that use rely on bitfield width/shift information.
|
||||
*/
|
||||
#define BITFMASK(field) (((1U << (field ## _WID)) - 1) << (field ## _LSH))
|
||||
#define BITFVAL(field, val) ((val) << (field ## _LSH))
|
||||
#define BITFEXT(var, bit) ((var & BITFMASK(bit)) >> (bit ## _LSH))
|
||||
|
||||
/*
|
||||
* Shift and width values for each register bitfield
|
||||
*/
|
||||
/* TMST_VALUE */
|
||||
#define TMST_VALUE_LSH 0
|
||||
#define TMST_VALUE_WID 8
|
||||
/* ENABLE */
|
||||
#define ACTIVE_LSH 7
|
||||
#define ACTIVE_WID 1
|
||||
#define STANDBY_LSH 6
|
||||
#define STANDBY_WID 1
|
||||
#define V3P3_SW_EN_LSH 5
|
||||
#define V3P3_SW_EN_WID 1
|
||||
#define VCOM_EN_LSH 4
|
||||
#define VCOM_EN_WID 1
|
||||
#define VDDH_EN_LSH 3
|
||||
#define VDDH_EN_WID 1
|
||||
#define VPOS_EN_LSH 2
|
||||
#define VPOS_EN_WID 1
|
||||
#define VEE_EN_LSH 1
|
||||
#define VEE_EN_WID 1
|
||||
#define VNEG_EN_LSH 0
|
||||
#define VNEG_EN_WID 1
|
||||
/* VCOM_ADJUST */
|
||||
#define VCOM_SET_LSH 0
|
||||
#define VCOM_SET_WID 8
|
||||
#define VCOM1_SET_LSH 0
|
||||
#define VCOM1_SET_WID 8
|
||||
#define VCOM2_SET_LSH 0
|
||||
#define VCOM2_SET_WID 1
|
||||
#define VCOM_ACQ_LSH 15
|
||||
#define VCOM_ACQ_WID 1
|
||||
#define VCOM_PROG_LSH 14
|
||||
#define VCOM_PEOG_WID 1
|
||||
#define VCOM_HiZ_LSH 13
|
||||
#define VCOM_HiZ_WID 1
|
||||
#define VCOM_AVG_LSH 11
|
||||
#define VCOM_AVG_WID 2
|
||||
/* INT_ENABLE1 */
|
||||
#define TSD_EN_LSH 6
|
||||
#define TSD_EN_WID 1
|
||||
#define HOT_EN_LSH 5
|
||||
#define HOT_EN_WID 1
|
||||
#define TMST_HOT_EN_LSH 4
|
||||
#define TMST_HOT_EN_WID 1
|
||||
#define TMST_COOL_EN_LSH 3
|
||||
#define TMST_COOL_EN_WID 1
|
||||
#define UVLO_EN_LSH 2
|
||||
#define UVLO_EN_WID 1
|
||||
/* INT_ENABLE2 */
|
||||
#define VB_UV_EN_LSH 7
|
||||
#define VB_UV_EN_WID 1
|
||||
#define VDDH_UV_EN_LSH 6
|
||||
#define VDDH_UV_EN_WID 1
|
||||
#define VN_UV_EN_LSH 5
|
||||
#define VN_UV_EN_WID 1
|
||||
#define VPOS_UV_EN_LSH 4
|
||||
#define VPOS_UV_EN_WID 1
|
||||
#define VEE_UV_EN_LSH 3
|
||||
#define VEE_UV_EN_WID 1
|
||||
#define VNEG_UV_EN_LSH 1
|
||||
#define VNEG_UV_EN_WID 1
|
||||
#define EOC_EN_LSH 0
|
||||
#define EOC_EN_WID 1
|
||||
/* INT_STATUS1 */
|
||||
#define TSDN_LSH 6
|
||||
#define TSDN_WID 1
|
||||
#define HOT_LSH 5
|
||||
#define HOT_WID 1
|
||||
#define TMST_HOT_LSH 4
|
||||
#define TMST_HOT_WID 1
|
||||
#define TMST_COOL_LSH 3
|
||||
#define TMST_COOL_WID 1
|
||||
#define UVLO_LSH 2
|
||||
#define UVLO_WID 1
|
||||
/* INT_STATUS2 */
|
||||
#define VB_UV_LSH 7
|
||||
#define VB_UV_WID 1
|
||||
#define VDDH_UV_LSH 6
|
||||
#define VDDH_UV_WID 1
|
||||
#define VN_UV_LSH 5
|
||||
#define VN_UV_WID 1
|
||||
#define VPOS_UV_LSH 4
|
||||
#define VPOS_UV_WID 1
|
||||
#define VEE_UV_LSH 3
|
||||
#define VEE_UV_WID 1
|
||||
#define VNEG_UV_LSH 1
|
||||
#define VNEG_UV_WID 1
|
||||
#define EOC_LSH 0
|
||||
#define EOC_WID 1
|
||||
/* PWR_SEQ0 */
|
||||
#define VDDH_SEQ_LSH 6
|
||||
#define VDDH_SEQ_WID 2
|
||||
#define VPOS_SEQ_LSH 4
|
||||
#define VPOS_SEQ_WID 2
|
||||
#define VEE_SEQ_LSH 2
|
||||
#define VEE_SEQ_WID 2
|
||||
#define VNEG_SEQ_LSH 0
|
||||
#define VNEG_SEQ_WID 2
|
||||
/* PWR_SEQ1 */
|
||||
#define DLY1_LSH 4
|
||||
#define DLY1_WID 4
|
||||
#define DLY0_LSH 0
|
||||
#define DLY0_WID 4
|
||||
/* PWR_SEQ2 */
|
||||
#define DLY3_LSH 4
|
||||
#define DLY3_WID 4
|
||||
#define DLY2_LSH 0
|
||||
#define DLY2_WID 4
|
||||
/* TMST_CONFIG */
|
||||
#define READ_THERM_LSH 7
|
||||
#define READ_THERM_WID 1
|
||||
#define CONV_END_LSH 5
|
||||
#define CONV_END_WID 1
|
||||
#define FAULT_QUE_LSH 3
|
||||
#define FAULT_QUE_WID 2
|
||||
#define FAULT_QUE_CLR_LSH 2
|
||||
#define FAULT_QUE_CLR_WID 1
|
||||
/* TMST_OS */
|
||||
#define TMST_HOT_SET_LSH 0
|
||||
#define TMST_HOT_SET_WID 8
|
||||
/* TMST_HYST */
|
||||
#define TMST_COOL_SET_LSH 0
|
||||
#define TMST_COOL_SET_WID 8
|
||||
/* PG_STATUS */
|
||||
#define VB_PG_LSH 7
|
||||
#define VB_PG_WID 1
|
||||
#define VDDH_PG_LSH 6
|
||||
#define VDDH_PG_WID 1
|
||||
#define VN_PG_LSH 5
|
||||
#define VN_PG_WID 1
|
||||
#define VPOS_PG_LSH 4
|
||||
#define VPOS_PG_WID 1
|
||||
#define VEE_PG_LSH 3
|
||||
#define VEE_PG_WID 1
|
||||
#define VNEG_PG_LSH 1
|
||||
#define VNEG_PG_WID 1
|
||||
/* REVID */
|
||||
#define MJREV_LSH 6
|
||||
#define MJREV_WID 2
|
||||
#define MNREV_LSH 4
|
||||
#define MNREV_WID 2
|
||||
#define VERSION_LSH 0
|
||||
#define VERSION_WID 4
|
||||
/* FIX_READ_POINTER */
|
||||
#define FIX_RD_PTR_LSH 0
|
||||
#define FIX_RD_PTR_WID 1
|
||||
|
||||
/*
|
||||
* VCOM Definitions
|
||||
*
|
||||
* The register fields accept voltages in the range 0V to -2.75V, but the
|
||||
* VCOM parametric performance is only guaranteed from -0.3V to -2.5V.
|
||||
*/
|
||||
#define TPS65180_VCOM_MIN_uV -2750000
|
||||
#define TPS65180_VCOM_MAX_uV 0
|
||||
#define TPS65180_VCOM_MIN_SET 0
|
||||
#define TPS65180_VCOM_MAX_SET 255
|
||||
#define TPS65180_VCOM_BASE_uV 10740
|
||||
#define TPS65180_VCOM_STEP_uV 10740
|
||||
#define TPS65185_VCOM_MIN_uV -5110000
|
||||
#define TPS65185_VCOM_MAX_uV 0
|
||||
#define TPS65185_VCOM_MIN_SET 0
|
||||
#define TPS65185_VCOM_MAX_SET 511
|
||||
#define TPS65185_VCOM_BASE_uV 10000
|
||||
#define TPS65185_VCOM_STEP_uV 10000
|
||||
|
||||
|
||||
|
||||
#define TPS6518x_VCOM_MIN_VAL 0
|
||||
#define TPS6518x_VCOM_MAX_VAL 255
|
||||
|
||||
struct regulator_init_data;
|
||||
|
||||
struct tps6518x {
|
||||
/* chip revision */
|
||||
int revID;
|
||||
|
||||
struct device *dev;
|
||||
struct tps6518x_platform_data *pdata;
|
||||
|
||||
/* Platform connection */
|
||||
struct i2c_client *i2c_client;
|
||||
|
||||
/* Timings */
|
||||
unsigned int pwr_seq0;
|
||||
unsigned int pwr_seq1;
|
||||
unsigned int pwr_seq2;
|
||||
unsigned int upseq0;
|
||||
unsigned int upseq1;
|
||||
unsigned int dwnseq0;
|
||||
unsigned int dwnseq1;
|
||||
|
||||
/* GPIOs */
|
||||
int gpio_pmic_pwrgood;
|
||||
int gpio_pmic_vcom_ctrl;
|
||||
int gpio_pmic_wakeup;
|
||||
int gpio_pmic_intr;
|
||||
int gpio_pmic_powerup;
|
||||
|
||||
/* TPS6518x part variables */
|
||||
int pass_num;
|
||||
int vcom_uV;
|
||||
|
||||
/* One-time VCOM setup marker */
|
||||
bool vcom_setup;
|
||||
|
||||
/* powerup/powerdown wait time */
|
||||
int max_wait;
|
||||
|
||||
/* Dynamically determined polarity for PWRGOOD */
|
||||
int pwrgood_polarity;
|
||||
};
|
||||
|
||||
enum {
|
||||
/* In alphabetical order */
|
||||
TPS6518x_DISPLAY, /* virtual master enable */
|
||||
TPS6518x_VCOM,
|
||||
TPS6518x_V3P3,
|
||||
TPS6518x_NUM_REGULATORS,
|
||||
};
|
||||
|
||||
/*
|
||||
* Declarations
|
||||
*/
|
||||
struct regulator_init_data;
|
||||
struct tps6518x_regulator_data;
|
||||
|
||||
struct tps6518x_platform_data {
|
||||
unsigned int pwr_seq0;
|
||||
unsigned int pwr_seq1;
|
||||
unsigned int pwr_seq2;
|
||||
unsigned int upseq0;
|
||||
unsigned int upseq1;
|
||||
unsigned int dwnseq0;
|
||||
unsigned int dwnseq1;
|
||||
int gpio_pmic_pwrgood;
|
||||
int gpio_pmic_vcom_ctrl;
|
||||
int gpio_pmic_wakeup;
|
||||
int gpio_pmic_intr;
|
||||
int gpio_pmic_powerup;
|
||||
int pass_num;
|
||||
int vcom_uV;
|
||||
|
||||
/* PMIC */
|
||||
struct tps6518x_regulator_data *regulators;
|
||||
int num_regulators;
|
||||
};
|
||||
|
||||
struct tps6518x_regulator_data {
|
||||
int id;
|
||||
struct regulator_init_data *initdata;
|
||||
struct device_node *reg_node;
|
||||
};
|
||||
|
||||
int tps6518x_reg_read(int reg_num, unsigned int *reg_val);
|
||||
int tps6518x_reg_write(int reg_num, const unsigned int reg_val);
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue