1
0
Fork 0

sy7636a EPD PMIC driver initial commit

Add multi-function device to interface the
sy7636a EPD PMIC chip from Silergy.

- Regulator driver for VCOM
- Hwmon driver for thermistor temperature
- MFD driver for i2c regmap
pull/10/head
Lars Ivar Miljeteig 2019-08-28 11:06:58 +02:00 committed by Steinar Bakkemo
parent f732531df4
commit 26f5dca610
10 changed files with 356 additions and 0 deletions

View File

@ -1364,6 +1364,16 @@ config SENSORS_SIS5595
This driver can also be built as a module. If so, the module
will be called sis5595.
config SENSORS_SY7636A
tristate "Silergy SY7636A"
depends on I2C
help
If you say yes here you get support for the thermistor readout of
the Silergy SY7636A PMIC.
This driver can also be built as a module. If so, the module
will be called sy7636a-hwmon.
config SENSORS_DME1737
tristate "SMSC DME1737, SCH311x and compatibles"
depends on I2C && !PPC

View File

@ -153,6 +153,7 @@ obj-$(CONFIG_SENSORS_SMSC47B397)+= smsc47b397.o
obj-$(CONFIG_SENSORS_SMSC47M1) += smsc47m1.o
obj-$(CONFIG_SENSORS_SMSC47M192)+= smsc47m192.o
obj-$(CONFIG_SENSORS_STTS751) += stts751.o
obj-$(CONFIG_SENSORS_SY7636A) += sy7636a-hwmon.o
obj-$(CONFIG_SENSORS_AMC6821) += amc6821.o
obj-$(CONFIG_SENSORS_TC74) += tc74.o
obj-$(CONFIG_SENSORS_THMC50) += thmc50.o

View File

@ -0,0 +1,106 @@
/*
* Functions to access SY3686A power management chip temperature
*
* Copyright (C) 2019 reMarkable AS - http://www.remarkable.com/
*
* Author: Lars Ivar Miljeteig <lars.ivar.miljeteig@remarkable.com>
*
* 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 version 2.
*
* This program is distributed "as is" WITHOUT ANY WARRANTY of any
* kind, whether express or implied; without even the implied warranty
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#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/err.h>
#include <linux/sysfs.h>
#include <linux/platform_device.h>
#include <linux/mfd/sy7636a.h>
struct sy7636a_data {
struct sy7636a *sy7636a;
struct device *hwmon_dev;
};
static ssize_t show_temp(struct device *dev,
struct device_attribute *attr, char *buf)
{
unsigned int reg_val;
signed char temp;
int ret;
struct sy7636a_data *data = dev_get_drvdata(dev);
ret = regmap_read(data->sy7636a->regmap,
SY7636A_REG_TERMISTOR_READOUT, &reg_val);
if (ret)
return ret;
temp = *((signed char*)&reg_val);
return snprintf(buf, PAGE_SIZE, "%d\n", temp);
}
static SENSOR_DEVICE_ATTR(temp0, S_IRUGO, show_temp, NULL, 0);
static struct attribute *sy7636a_attrs[] = {
&sensor_dev_attr_temp0.dev_attr.attr,
NULL
};
ATTRIBUTE_GROUPS(sy7636a);
static int sy7636a_sensor_probe(struct platform_device *pdev)
{
struct sy7636a *sy7636a = dev_get_drvdata(pdev->dev.parent);
struct sy7636a_data *data;
int err;
if (!sy7636a)
return -EPROBE_DEFER;
data = devm_kzalloc(&pdev->dev, sizeof(struct sy7636a_data), GFP_KERNEL);
if (!data) {
return -ENOMEM;
}
data->sy7636a = sy7636a;
data->hwmon_dev = devm_hwmon_device_register_with_groups(&pdev->dev,
"sy7636a_temperature", data, sy7636a_groups);
if (IS_ERR(data->hwmon_dev)) {
err = PTR_ERR(data->hwmon_dev);
dev_err(&pdev->dev, "Unable to register hwmon device, returned %d", err);
return err;
}
return 0;
}
static const struct platform_device_id sy7636a_sensor_id[] = {
{ "sy7636a-temperature", 0},
{ },
};
MODULE_DEVICE_TABLE(platform, sy7636a_sensor_id);
static struct platform_driver sy7636a_sensor_driver = {
.probe = sy7636a_sensor_probe,
.id_table = sy7636a_sensor_id,
.driver = {
.name = "sy7636a-temperature",
},
};
module_platform_driver(sy7636a_sensor_driver);
MODULE_DESCRIPTION("SY7636A sensor driver");
MODULE_LICENSE("GPL");

View File

@ -1307,6 +1307,16 @@ config MFD_PALMAS
If you say yes here you get support for the Palmas
series of PMIC chips from Texas Instruments.
config MFD_SY7636A
tristate "Silergy SY7636A Power Management chip driver"
select MFD_CORE
select REGMAP_I2C
select REGMAP_IRQ
depends on I2C=y
help
If you say yes here you get support for the SY7636A
PMIC chip from Silergy
config TPS6105X
tristate "TI TPS61050/61052 Boost Converters"
depends on I2C

View File

@ -218,6 +218,7 @@ obj-$(CONFIG_MFD_HI655X_PMIC) += hi655x-pmic.o
obj-$(CONFIG_MFD_DLN2) += dln2.o
obj-$(CONFIG_MFD_RT5033) += rt5033.o
obj-$(CONFIG_MFD_SKY81452) += sky81452.o
obj-$(CONFIG_MFD_SY7636A) += sy7636a.o
obj-$(CONFIG_MFD_MXC_HDMI) += mxc-hdmi-core.o
intel-soc-pmic-objs := intel_soc_pmic_core.o intel_soc_pmic_crc.o

View File

@ -0,0 +1,82 @@
/*
* Copyright (C) 2019 reMarkable AS - http://www.remarkable.com/
*
* Author: Lars Ivar Miljeteig <lars.ivar.miljeteig@remarkable.com>
*
* 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 version 2.
*
* Based on the lp87565 driver by Keerthy <j-keerthy@ti.com>
*/
#include <linux/interrupt.h>
#include <linux/mfd/core.h>
#include <linux/module.h>
#include <linux/of_device.h>
#include <linux/regmap.h>
#include <linux/mfd/sy7636a.h>
static const struct regmap_config sy7636a_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
};
static const struct mfd_cell sy7636a_cells[] = {
{ .name = "sy7636a-regulator", },
{ .name = "sy7636a-temperature", },
};
static const struct of_device_id of_sy7636a_match_table[] = {
{ .compatible = "silergy,sy7636a", },
{}
};
MODULE_DEVICE_TABLE(of, of_sy7636a_match_table);
static int sy7636a_probe(struct i2c_client *client,
const struct i2c_device_id *ids)
{
struct sy7636a *sy7636a;
int ret;
sy7636a = devm_kzalloc(&client->dev, sizeof(struct sy7636a), GFP_KERNEL);
if (sy7636a == NULL)
return -ENOMEM;
sy7636a->dev = &client->dev;
sy7636a->regmap = devm_regmap_init_i2c(client, &sy7636a_regmap_config);
if (IS_ERR(sy7636a->regmap)) {
ret = PTR_ERR(sy7636a->regmap);
dev_err(sy7636a->dev,
"Failed to initialize register map: %d\n", ret);
return ret;
}
i2c_set_clientdata(client, sy7636a);
return devm_mfd_add_devices(sy7636a->dev, PLATFORM_DEVID_AUTO,
sy7636a_cells, ARRAY_SIZE(sy7636a_cells),
NULL, 0, NULL);
}
static const struct i2c_device_id sy7636a_id_table[] = {
{ "sy7636a", 0 },
{ },
};
MODULE_DEVICE_TABLE(i2c, sy7636a_id_table);
static struct i2c_driver sy7636a_driver = {
.driver = {
.name = "sy7636a",
.of_match_table = of_sy7636a_match_table,
},
.probe = sy7636a_probe,
.id_table = sy7636a_id_table,
};
module_i2c_driver(sy7636a_driver);
MODULE_AUTHOR("Lars Ivar Miljeteig <lars.ivar.miljeteig@remarkable.com>");
MODULE_DESCRIPTION("Silergy SY7636A Multi-Function Device Driver");
MODULE_LICENSE("GPL v2");

View File

@ -787,6 +787,12 @@ config REGULATOR_SKY81452
This driver can also be built as a module. If so, the module
will be called sky81452-regulator.
config REGULATOR_SY7636A
tristate "Silergy SY7636A voltage regulator"
depends on MFD_SY7636A
help
This driver supports Silergy SY3686A voltage regulator.
config REGULATOR_STM32_VREFBUF
tristate "STMicroelectronics STM32 VREFBUF"
depends on ARCH_STM32 || COMPILE_TEST

View File

@ -101,6 +101,7 @@ obj-$(CONFIG_REGULATOR_S2MPA01) += s2mpa01.o
obj-$(CONFIG_REGULATOR_S2MPS11) += s2mps11.o
obj-$(CONFIG_REGULATOR_S5M8767) += s5m8767.o
obj-$(CONFIG_REGULATOR_SKY81452) += sky81452-regulator.o
obj-$(CONFIG_REGULATOR_SY7636A) += sy7636a-regulator.o
obj-$(CONFIG_REGULATOR_STM32_VREFBUF) += stm32-vrefbuf.o
obj-$(CONFIG_REGULATOR_STW481X_VMMC) += stw481x-vmmc.o
obj-$(CONFIG_REGULATOR_TI_ABB) += ti-abb-regulator.o

View File

@ -0,0 +1,97 @@
/*
* Functions to access SY3686A power management chip voltages
*
* Copyright (C) 2019 reMarkable AS - http://www.remarkable.com/
*
* Author: Lars Ivar Miljeteig <lars.ivar.miljeteig@remarkable.com>
*
* 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 version 2.
*
* This program is distributed "as is" WITHOUT ANY WARRANTY of any
* kind, whether express or implied; without even the implied warranty
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
#include <linux/mfd/sy7636a.h>
static int get_vcom_voltage(struct regulator_dev *rdev)
{
int ret;
unsigned int val;
ret = regmap_read(rdev->regmap, SY7636A_REG_VCOM_ADJUST_CTRL_L, &val);
if (ret)
return ret;
return (val & 0x1FF) * 10;
}
static const struct regulator_ops sy7636a_vcom_volt_ops = {
.get_voltage = get_vcom_voltage,
.enable = regulator_enable_regmap,
.disable = regulator_disable_regmap,
.is_enabled = regulator_is_enabled_regmap,
};
struct regulator_desc desc = {
.name = "vcom",
.supply_name = "vcom-in",
.id = 0,
.ops = &sy7636a_vcom_volt_ops,
.type = REGULATOR_VOLTAGE,
.owner = THIS_MODULE,
.enable_reg = SY7636A_REG_OPERATION_MODE_CRL,
.enable_mask = SY7636A_OPERATION_MODE_CRL_ONOFF,
};
static int sy7636a_regulator_probe(struct platform_device *pdev)
{
struct sy7636a *sy7636a = dev_get_drvdata(pdev->dev.parent);
struct regulator_config config = { };
struct regulator_dev *rdev;
if (!sy7636a)
return -EPROBE_DEFER;
platform_set_drvdata(pdev, sy7636a);
config.dev = &pdev->dev;
config.dev->of_node = sy7636a->dev->of_node;
config.driver_data = sy7636a;
config.regmap = sy7636a->regmap;
rdev = devm_regulator_register(&pdev->dev, &desc, &config);
if (IS_ERR(rdev)) {
dev_err(sy7636a->dev, "failed to register %s regulator\n",
pdev->name);
return PTR_ERR(rdev);
}
return 0;
}
static const struct platform_device_id sy7636a_regulator_id_table[] = {
{ "sy7636a-regulator", },
};
MODULE_DEVICE_TABLE(platform, sy7636a_regulator_id_table);
static struct platform_driver sy7636a_regulator_driver = {
.driver = {
.name = "sy7636a-regulator",
},
.probe = sy7636a_regulator_probe,
.id_table = sy7636a_regulator_id_table,
};
module_platform_driver(sy7636a_regulator_driver);
MODULE_AUTHOR("Lars Ivar Miljeteig <lars.ivar.miljeteig@remarkable.com>");
MODULE_DESCRIPTION("SY7636A voltage regulator driver");
MODULE_LICENSE("GPL v2");

View File

@ -0,0 +1,42 @@
/*
* Functions to access SY3686A power management chip.
*
* Copyright (C) 2019 reMarkable AS - http://www.remarkable.com/
*
* 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 version 2.
*
* This program is distributed "as is" WITHOUT ANY WARRANTY of any
* kind, whether express or implied; without even the implied warranty
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#ifndef __LINUX_MFD_SY7636A_H
#define __LINUX_MFD_SY7636A_H
#include <linux/i2c.h>
#include <linux/regulator/driver.h>
#include <linux/regulator/machine.h>
#include <linux/regmap.h>
#define SY7636A_REG_OPERATION_MODE_CRL 0x00
#define SY7636A_OPERATION_MODE_CRL_VCOMCTL (1 << 6)
#define SY7636A_OPERATION_MODE_CRL_ONOFF (1 << 7)
#define SY7636A_REG_VCOM_ADJUST_CTRL_L 0x01
#define SY7636A_REG_VCOM_ADJUST_CTRL_H 0x02
#define SY7636A_REG_VCOM_ADJUST_CTRL_MASK 0x01ff
#define SY7636A_REG_VLDO_VOLTAGE_ADJULST_CTRL 0x03
#define SY7636A_REG_POWER_ON_DELAY_TIME 0x06
#define SY7636A_REG_FAULT_FLAG 0x07
#define SY7636A_REG_TERMISTOR_READOUT 0x08
#define SY7636A_REG_MAX 0x08
struct sy7636a {
struct device *dev;
struct regmap *regmap;
};
#endif /* __LINUX_MFD_SY7636A_H */