From 9c61fd3e36c16e71823121fb4b54827d45e81cc4 Mon Sep 17 00:00:00 2001 From: Shenfei xu Date: Fri, 8 Jan 2016 18:57:17 +0800 Subject: [PATCH] mfd: RK818: add new mfd driver for 818. Change-Id: Iae0797ad17701a81ca91bc2396bfc2ec16241231 Signed-off-by: Shenfei xu --- drivers/mfd/rk808.c | 182 ++++++++++- drivers/regulator/Kconfig | 10 + drivers/regulator/Makefile | 1 + drivers/regulator/rk818-regulator.c | 467 ++++++++++++++++++++++++++++ include/linux/mfd/rk808.h | 199 ++++++++++++ 5 files changed, 845 insertions(+), 14 deletions(-) create mode 100644 drivers/regulator/rk818-regulator.c diff --git a/drivers/mfd/rk808.c b/drivers/mfd/rk808.c index 4b1e4399754b..1dafebac68ac 100644 --- a/drivers/mfd/rk808.c +++ b/drivers/mfd/rk808.c @@ -22,6 +22,7 @@ #include #include #include +#include struct rk808_reg_data { int addr; @@ -29,6 +30,16 @@ struct rk808_reg_data { int value; }; +struct rk8xx_power_data { + char *name; + const struct rk808_reg_data *rk8xx_pre_init_reg; + int reg_num; + const struct regmap_config *rk8xx_regmap_config; + const struct mfd_cell *rk8xx_cell; + int cell_num; + struct regmap_irq_chip *rk8xx_irq_chip; +}; + static bool rk808_is_volatile_reg(struct device *dev, unsigned int reg) { /* @@ -148,6 +159,130 @@ static struct regmap_irq_chip rk808_irq_chip = { .init_ack_masked = true, }; +static const struct regmap_config rk818_regmap_config = { + .reg_bits = 8, + .val_bits = 8, + .max_register = RK818_SAVE_DATA19, + .cache_type = REGCACHE_RBTREE, + .volatile_reg = rk808_is_volatile_reg, +}; + +static const struct mfd_cell rk818s[] = { + { .name = "rk808-clkout", }, + { .name = "rk818-regulator", }, + { + .name = "rk808-rtc", + .num_resources = ARRAY_SIZE(rtc_resources), + .resources = &rtc_resources[0], + }, +}; + +static const struct rk808_reg_data rk818_pre_init_reg[] = { + { RK818_H5V_EN_REG, REF_RDY_CTRL_ENABLE | H5V_EN_MASK, + REF_RDY_CTRL_ENABLE | H5V_EN_ENABLE }, + { RK818_DCDC_EN_REG, BOOST_EN_MASK | SWITCH_EN_MASK, + BOOST_EN_ENABLE | SWITCH_EN_ENABLE }, + { RK818_SLEEP_SET_OFF_REG1, OTG_SLP_SET_MASK, OTG_SLP_SET_OFF }, + { RK818_BUCK4_CONFIG_REG, BUCK_ILMIN_MASK, BUCK_ILMIN_250MA }, +}; + +static const struct regmap_irq rk818_irqs[] = { + /* INT_STS */ + [RK818_IRQ_VOUT_LO] = { + .mask = VOUT_LO_MASK, + .reg_offset = 0, + }, + [RK818_IRQ_VB_LO] = { + .mask = VB_LO_MASK, + .reg_offset = 0, + }, + [RK818_IRQ_PWRON] = { + .mask = PWRON_MASK, + .reg_offset = 0, + }, + [RK818_IRQ_PWRON_LP] = { + .mask = PWRON_LP_MASK, + .reg_offset = 0, + }, + [RK818_IRQ_HOTDIE] = { + .mask = HOTDIE_MASK, + .reg_offset = 0, + }, + [RK818_IRQ_RTC_ALARM] = { + .mask = RTC_ALARM_MASK, + .reg_offset = 0, + }, + [RK818_IRQ_RTC_PERIOD] = { + .mask = RTC_PERIOD_MASK, + .reg_offset = 0, + }, + [RK818_IRQ_USB_OV] = { + .mask = USB_OV_MASK, + .reg_offset = 0, + }, + /* INT_STS2 */ + [RK818_IRQ_PLUG_IN] = { + .mask = PLUG_IN_MASK, + .reg_offset = 1, + }, + [RK818_IRQ_PLUG_OUT] = { + .mask = PLUG_OUT_MASK, + .reg_offset = 1, + }, + [RK818_IRQ_CHG_OK] = { + .mask = CHGOK_MASK, + .reg_offset = 1, + }, + [RK818_IRQ_CHG_TE] = { + .mask = CHGTE_MASK, + .reg_offset = 1, + }, + [RK818_IRQ_CHG_TS1] = { + .mask = CHGTS1_MASK, + .reg_offset = 1, + }, + [RK818_IRQ_TS2] = { + .mask = TS2_MASK, + .reg_offset = 1, + }, + [RK818_IRQ_DISCHG_ILIM] = { + .mask = DISCHG_ILIM_MASK, + .reg_offset = 1, + }, +}; + +static struct regmap_irq_chip rk818_irq_chip = { + .name = "rk818", + .irqs = rk818_irqs, + .num_irqs = ARRAY_SIZE(rk818_irqs), + .num_regs = 2, + .irq_reg_stride = 2, + .status_base = RK808_INT_STS_REG1, + .mask_base = RK808_INT_STS_MSK_REG1, + .ack_base = RK808_INT_STS_REG1, + .init_ack_masked = true, +}; + +static struct rk8xx_power_data rk808_power_data = { + .name = "rk808", + .rk8xx_pre_init_reg = pre_init_reg, + .reg_num = ARRAY_SIZE(pre_init_reg), + .rk8xx_regmap_config = &rk808_regmap_config, + .rk8xx_cell = rk808s, + .cell_num = ARRAY_SIZE(rk808s), + .rk8xx_irq_chip = &rk808_irq_chip, +}; + +static struct rk8xx_power_data rk818_power_data = { + .name = "rk818", + .rk8xx_pre_init_reg = rk818_pre_init_reg, + .reg_num = ARRAY_SIZE(rk818_pre_init_reg), + .rk8xx_regmap_config = &rk818_regmap_config, + .rk8xx_cell = rk818s, + .cell_num = ARRAY_SIZE(rk818s), + .rk8xx_irq_chip = &rk818_irq_chip, +}; + static struct i2c_client *rk808_i2c_client; static void rk808_device_shutdown(void) { @@ -167,15 +302,36 @@ static void rk808_device_shutdown(void) dev_err(&rk808_i2c_client->dev, "power off error!\n"); } +static const struct of_device_id rk808_of_match[] = { + { + .compatible = "rockchip,rk808", + .data = &rk808_power_data, + }, + { + .compatible = "rockchip,rk818", + .data = &rk818_power_data, + }, + { }, +}; +MODULE_DEVICE_TABLE(of, rk808_of_match); + static int rk808_probe(struct i2c_client *client, const struct i2c_device_id *id) { + const struct of_device_id *of_id = + of_match_device(rk808_of_match, &client->dev); + const struct rk8xx_power_data *pdata = of_id->data; struct device_node *np = client->dev.of_node; struct rk808 *rk808; int pm_off = 0; int ret; int i; + if (!of_id) { + dev_err(&client->dev, "Failed to find matching dt id\n"); + return -ENODEV; + } + if (!client->irq) { dev_err(&client->dev, "No interrupt support, no core IRQ\n"); return -EINVAL; @@ -185,26 +341,29 @@ static int rk808_probe(struct i2c_client *client, if (!rk808) return -ENOMEM; - rk808->regmap = devm_regmap_init_i2c(client, &rk808_regmap_config); + rk808->regmap = devm_regmap_init_i2c(client, + pdata->rk8xx_regmap_config); if (IS_ERR(rk808->regmap)) { dev_err(&client->dev, "regmap initialization failed\n"); return PTR_ERR(rk808->regmap); } - for (i = 0; i < ARRAY_SIZE(pre_init_reg); i++) { - ret = regmap_update_bits(rk808->regmap, pre_init_reg[i].addr, - pre_init_reg[i].mask, - pre_init_reg[i].value); + for (i = 0; i < pdata->reg_num; i++) { + ret = regmap_update_bits(rk808->regmap, + pdata->rk8xx_pre_init_reg[i].addr, + pdata->rk8xx_pre_init_reg[i].mask, + pdata->rk8xx_pre_init_reg[i].value); if (ret) { dev_err(&client->dev, - "0x%x write err\n", pre_init_reg[i].addr); + "0x%x write err\n", + pdata->rk8xx_pre_init_reg[i].addr); return ret; } } ret = regmap_add_irq_chip(rk808->regmap, client->irq, IRQF_ONESHOT, -1, - &rk808_irq_chip, &rk808->irq_data); + pdata->rk8xx_irq_chip, &rk808->irq_data); if (ret) { dev_err(&client->dev, "Failed to add irq_chip %d\n", ret); return ret; @@ -214,7 +373,7 @@ static int rk808_probe(struct i2c_client *client, i2c_set_clientdata(client, rk808); ret = mfd_add_devices(&client->dev, -1, - rk808s, ARRAY_SIZE(rk808s), + pdata->rk8xx_cell, pdata->cell_num, NULL, 0, regmap_irq_get_domain(rk808->irq_data)); if (ret) { dev_err(&client->dev, "failed to add MFD devices %d\n", ret); @@ -246,14 +405,9 @@ static int rk808_remove(struct i2c_client *client) return 0; } -static const struct of_device_id rk808_of_match[] = { - { .compatible = "rockchip,rk808" }, - { }, -}; -MODULE_DEVICE_TABLE(of, rk808_of_match); - static const struct i2c_device_id rk808_ids[] = { { "rk808" }, + { "rk818" }, { }, }; MODULE_DEVICE_TABLE(i2c, rk808_ids); diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig index 99cbb77ec754..9f7da20920a7 100644 --- a/drivers/regulator/Kconfig +++ b/drivers/regulator/Kconfig @@ -566,6 +566,16 @@ config REGULATOR_RK808 through regulator interface. The device supports multiple DCDC/LDO outputs which can be controlled by i2c communication. +config REGULATOR_RK818 + tristate "Rockchip RK818 Power regulators" + depends on MFD_RK808 + help + Select this option to enable the power regulator of ROCKCHIP + PMIC RK818. + This driver supports the control of different power rails of device + through regulator interface. The device supports multiple DCDC/LDO + outputs which can be controlled by i2c communication. + config REGULATOR_RN5T618 tristate "Ricoh RN5T618 voltage regulators" depends on MFD_RN5T618 diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile index 9a54c8aa7746..f75549ba075a 100644 --- a/drivers/regulator/Makefile +++ b/drivers/regulator/Makefile @@ -73,6 +73,7 @@ obj-$(CONFIG_REGULATOR_PCAP) += pcap-regulator.o obj-$(CONFIG_REGULATOR_PCF50633) += pcf50633-regulator.o obj-$(CONFIG_REGULATOR_RC5T583) += rc5t583-regulator.o obj-$(CONFIG_REGULATOR_RK808) += rk808-regulator.o +obj-$(CONFIG_REGULATOR_RK818) += rk818-regulator.o obj-$(CONFIG_REGULATOR_RN5T618) += rn5t618-regulator.o obj-$(CONFIG_REGULATOR_RT5033) += rt5033-regulator.o obj-$(CONFIG_REGULATOR_S2MPA01) += s2mpa01.o diff --git a/drivers/regulator/rk818-regulator.c b/drivers/regulator/rk818-regulator.c new file mode 100644 index 000000000000..6fe92365498a --- /dev/null +++ b/drivers/regulator/rk818-regulator.c @@ -0,0 +1,467 @@ +/* + * Regulator driver for Rockchip RK818 + * + * Copyright (c) 2016, Fuzhou Rockchip Electronics Co., Ltd + * + * Author: xsf + * Author: Zhang Qing + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Field Definitions */ +#define RK818_BUCK_VSEL_MASK 0x3f +#define RK818_BUCK4_VSEL_MASK 0x1f +#define RK818_LDO_VSEL_MASK 0x1f +#define RK818_LDO3_VSEL_MASK 0x0f + +/* Ramp rate definitions for buck1 / buck2 only */ +#define RK818_RAMP_RATE_OFFSET 3 +#define RK818_RAMP_RATE_MASK (3 << RK818_RAMP_RATE_OFFSET) +#define RK818_RAMP_RATE_2MV_PER_US (0 << RK818_RAMP_RATE_OFFSET) +#define RK818_RAMP_RATE_4MV_PER_US (1 << RK818_RAMP_RATE_OFFSET) +#define RK818_RAMP_RATE_6MV_PER_US (2 << RK818_RAMP_RATE_OFFSET) +#define RK818_RAMP_RATE_10MV_PER_US (3 << RK818_RAMP_RATE_OFFSET) + +/* Offset from XXX_ON_VSEL to XXX_SLP_VSEL */ +#define RK818_SLP_REG_OFFSET 1 + +/* Offset from XXX_EN_REG to SLEEP_SET_OFF_XXX */ +#define RK818_SLP_SET_OFF_REG_OFFSET 2 + +/* max steps for increase voltage of Buck1/2, equal 100mv*/ +#define MAX_STEPS_ONE_TIME 8 + +static const int rk818_buck_config_regs[] = { + RK818_BUCK1_CONFIG_REG, + RK818_BUCK2_CONFIG_REG, + RK818_BUCK3_CONFIG_REG, + RK818_BUCK4_CONFIG_REG, +}; + +static const struct regulator_linear_range rk818_buck_voltage_ranges[] = { + REGULATOR_LINEAR_RANGE(712500, 0, 63, 12500), +}; + +static const struct regulator_linear_range rk818_buck4_voltage_ranges[] = { + REGULATOR_LINEAR_RANGE(1800000, 0, 15, 100000), +}; + +static const struct regulator_linear_range rk818_ldo_voltage_ranges[] = { + REGULATOR_LINEAR_RANGE(1800000, 0, 16, 100000), +}; + +static const struct regulator_linear_range rk818_ldo3_voltage_ranges[] = { + REGULATOR_LINEAR_RANGE(800000, 0, 13, 100000), + REGULATOR_LINEAR_RANGE(2500000, 15, 15, 0), +}; + +static const struct regulator_linear_range rk818_ldo6_voltage_ranges[] = { + REGULATOR_LINEAR_RANGE(800000, 0, 17, 100000), +}; + +static int rk818_set_ramp_delay(struct regulator_dev *rdev, int ramp_delay) +{ + unsigned int ramp_value = RK818_RAMP_RATE_10MV_PER_US; + unsigned int reg = rk818_buck_config_regs[rdev->desc->id - + RK818_ID_DCDC1]; + + switch (ramp_delay) { + case 1 ... 2000: + ramp_value = RK818_RAMP_RATE_2MV_PER_US; + break; + case 2001 ... 4000: + ramp_value = RK818_RAMP_RATE_4MV_PER_US; + break; + case 4001 ... 6000: + ramp_value = RK818_RAMP_RATE_6MV_PER_US; + break; + case 6001 ... 10000: + break; + default: + pr_warn("%s ramp_delay: %d not supported, setting 10000\n", + rdev->desc->name, ramp_delay); + } + + return regmap_update_bits(rdev->regmap, reg, + RK818_RAMP_RATE_MASK, ramp_value); +} + +static int rk818_set_suspend_voltage(struct regulator_dev *rdev, int uv) +{ + unsigned int reg; + int sel = regulator_map_voltage_linear_range(rdev, uv, uv); + + if (sel < 0) + return -EINVAL; + + reg = rdev->desc->vsel_reg + RK818_SLP_REG_OFFSET; + + return regmap_update_bits(rdev->regmap, reg, + rdev->desc->vsel_mask, + sel); +} + +static int rk818_set_suspend_enable(struct regulator_dev *rdev) +{ + unsigned int reg; + + reg = rdev->desc->enable_reg + RK818_SLP_SET_OFF_REG_OFFSET; + + return regmap_update_bits(rdev->regmap, reg, + rdev->desc->enable_mask, + 0); +} + +static int rk818_set_suspend_disable(struct regulator_dev *rdev) +{ + unsigned int reg; + + reg = rdev->desc->enable_reg + RK818_SLP_SET_OFF_REG_OFFSET; + + return regmap_update_bits(rdev->regmap, reg, + rdev->desc->enable_mask, + rdev->desc->enable_mask); +} + +static struct regulator_ops rk818_buck1_2_ops = { + .list_voltage = regulator_list_voltage_linear_range, + .map_voltage = regulator_map_voltage_linear_range, + .get_voltage_sel = regulator_get_voltage_sel_regmap, + .set_voltage_sel = regulator_set_voltage_sel_regmap, + .set_voltage_time_sel = regulator_set_voltage_time_sel, + .enable = regulator_enable_regmap, + .disable = regulator_disable_regmap, + .is_enabled = regulator_is_enabled_regmap, + .set_ramp_delay = rk818_set_ramp_delay, + .set_suspend_voltage = rk818_set_suspend_voltage, + .set_suspend_enable = rk818_set_suspend_enable, + .set_suspend_disable = rk818_set_suspend_disable, +}; + +static struct regulator_ops rk818_reg_ops = { + .list_voltage = regulator_list_voltage_linear_range, + .map_voltage = regulator_map_voltage_linear_range, + .get_voltage_sel = regulator_get_voltage_sel_regmap, + .set_voltage_sel = regulator_set_voltage_sel_regmap, + .enable = regulator_enable_regmap, + .disable = regulator_disable_regmap, + .is_enabled = regulator_is_enabled_regmap, + .set_suspend_voltage = rk818_set_suspend_voltage, + .set_suspend_enable = rk818_set_suspend_enable, + .set_suspend_disable = rk818_set_suspend_disable, +}; + +static struct regulator_ops rk818_switch_ops = { + .enable = regulator_enable_regmap, + .disable = regulator_disable_regmap, + .is_enabled = regulator_is_enabled_regmap, + .set_suspend_enable = rk818_set_suspend_enable, + .set_suspend_disable = rk818_set_suspend_disable, +}; + +static const struct regulator_desc rk818_reg[] = { + { + .name = "DCDC_REG1", + .supply_name = "vcc1", + .id = RK818_ID_DCDC1, + .ops = &rk818_buck1_2_ops, + .type = REGULATOR_VOLTAGE, + .n_voltages = 64, + .linear_ranges = rk818_buck_voltage_ranges, + .n_linear_ranges = ARRAY_SIZE(rk818_buck_voltage_ranges), + .vsel_reg = RK818_BUCK1_ON_VSEL_REG, + .vsel_mask = RK818_BUCK_VSEL_MASK, + .enable_reg = RK818_DCDC_EN_REG, + .enable_mask = BIT(0), + .owner = THIS_MODULE, + }, { + .name = "DCDC_REG2", + .supply_name = "vcc2", + .id = RK818_ID_DCDC2, + .ops = &rk818_buck1_2_ops, + .type = REGULATOR_VOLTAGE, + .n_voltages = 64, + .linear_ranges = rk818_buck_voltage_ranges, + .n_linear_ranges = ARRAY_SIZE(rk818_buck_voltage_ranges), + .vsel_reg = RK818_BUCK2_ON_VSEL_REG, + .vsel_mask = RK818_BUCK_VSEL_MASK, + .enable_reg = RK818_DCDC_EN_REG, + .enable_mask = BIT(1), + .owner = THIS_MODULE, + }, { + .name = "DCDC_REG3", + .supply_name = "vcc3", + .id = RK818_ID_DCDC3, + .ops = &rk818_switch_ops, + .type = REGULATOR_VOLTAGE, + .n_voltages = 1, + .enable_reg = RK818_DCDC_EN_REG, + .enable_mask = BIT(2), + .owner = THIS_MODULE, + }, { + .name = "DCDC_REG4", + .supply_name = "vcc4", + .id = RK818_ID_DCDC4, + .ops = &rk818_reg_ops, + .type = REGULATOR_VOLTAGE, + .n_voltages = 16, + .linear_ranges = rk818_buck4_voltage_ranges, + .n_linear_ranges = ARRAY_SIZE(rk818_buck4_voltage_ranges), + .vsel_reg = RK818_BUCK4_ON_VSEL_REG, + .vsel_mask = RK818_BUCK4_VSEL_MASK, + .enable_reg = RK818_DCDC_EN_REG, + .enable_mask = BIT(3), + .owner = THIS_MODULE, + }, { + .name = "LDO_REG1", + .supply_name = "vcc6", + .id = RK818_ID_LDO1, + .ops = &rk818_reg_ops, + .type = REGULATOR_VOLTAGE, + .n_voltages = 17, + .linear_ranges = rk818_ldo_voltage_ranges, + .n_linear_ranges = ARRAY_SIZE(rk818_ldo_voltage_ranges), + .vsel_reg = RK818_LDO1_ON_VSEL_REG, + .vsel_mask = RK818_LDO_VSEL_MASK, + .enable_reg = RK818_LDO_EN_REG, + .enable_mask = BIT(0), + .enable_time = 400, + .owner = THIS_MODULE, + }, { + .name = "LDO_REG2", + .supply_name = "vcc6", + .id = RK818_ID_LDO2, + .ops = &rk818_reg_ops, + .type = REGULATOR_VOLTAGE, + .n_voltages = 17, + .linear_ranges = rk818_ldo_voltage_ranges, + .n_linear_ranges = ARRAY_SIZE(rk818_ldo_voltage_ranges), + .vsel_reg = RK818_LDO2_ON_VSEL_REG, + .vsel_mask = RK818_LDO_VSEL_MASK, + .enable_reg = RK818_LDO_EN_REG, + .enable_mask = BIT(1), + .enable_time = 400, + .owner = THIS_MODULE, + }, { + .name = "LDO_REG3", + .supply_name = "vcc7", + .id = RK818_ID_LDO3, + .ops = &rk818_reg_ops, + .type = REGULATOR_VOLTAGE, + .n_voltages = 16, + .linear_ranges = rk818_ldo3_voltage_ranges, + .n_linear_ranges = ARRAY_SIZE(rk818_ldo3_voltage_ranges), + .vsel_reg = RK818_LDO3_ON_VSEL_REG, + .vsel_mask = RK818_LDO3_VSEL_MASK, + .enable_reg = RK818_LDO_EN_REG, + .enable_mask = BIT(2), + .enable_time = 400, + .owner = THIS_MODULE, + }, { + .name = "LDO_REG4", + .supply_name = "vcc8", + .id = RK818_ID_LDO4, + .ops = &rk818_reg_ops, + .type = REGULATOR_VOLTAGE, + .n_voltages = 17, + .linear_ranges = rk818_ldo_voltage_ranges, + .n_linear_ranges = ARRAY_SIZE(rk818_ldo_voltage_ranges), + .vsel_reg = RK818_LDO4_ON_VSEL_REG, + .vsel_mask = RK818_LDO_VSEL_MASK, + .enable_reg = RK818_LDO_EN_REG, + .enable_mask = BIT(3), + .enable_time = 400, + .owner = THIS_MODULE, + }, { + .name = "LDO_REG5", + .supply_name = "vcc7", + .id = RK818_ID_LDO5, + .ops = &rk818_reg_ops, + .type = REGULATOR_VOLTAGE, + .n_voltages = 17, + .linear_ranges = rk818_ldo_voltage_ranges, + .n_linear_ranges = ARRAY_SIZE(rk818_ldo_voltage_ranges), + .vsel_reg = RK818_LDO5_ON_VSEL_REG, + .vsel_mask = RK818_LDO_VSEL_MASK, + .enable_reg = RK818_LDO_EN_REG, + .enable_mask = BIT(4), + .enable_time = 400, + .owner = THIS_MODULE, + }, { + .name = "LDO_REG6", + .supply_name = "vcc8", + .id = RK818_ID_LDO6, + .ops = &rk818_reg_ops, + .type = REGULATOR_VOLTAGE, + .n_voltages = 18, + .linear_ranges = rk818_ldo6_voltage_ranges, + .n_linear_ranges = ARRAY_SIZE(rk818_ldo6_voltage_ranges), + .vsel_reg = RK818_LDO6_ON_VSEL_REG, + .vsel_mask = RK818_LDO_VSEL_MASK, + .enable_reg = RK818_LDO_EN_REG, + .enable_mask = BIT(5), + .enable_time = 400, + .owner = THIS_MODULE, + }, { + .name = "LDO_REG7", + .supply_name = "vcc7", + .id = RK818_ID_LDO7, + .ops = &rk818_reg_ops, + .type = REGULATOR_VOLTAGE, + .n_voltages = 18, + .linear_ranges = rk818_ldo6_voltage_ranges, + .n_linear_ranges = ARRAY_SIZE(rk818_ldo6_voltage_ranges), + .vsel_reg = RK818_LDO7_ON_VSEL_REG, + .vsel_mask = RK818_LDO_VSEL_MASK, + .enable_reg = RK818_LDO_EN_REG, + .enable_mask = BIT(6), + .enable_time = 400, + .owner = THIS_MODULE, + }, { + .name = "LDO_REG8", + .supply_name = "vcc8", + .id = RK818_ID_LDO8, + .ops = &rk818_reg_ops, + .type = REGULATOR_VOLTAGE, + .n_voltages = 17, + .linear_ranges = rk818_ldo_voltage_ranges, + .n_linear_ranges = ARRAY_SIZE(rk818_ldo_voltage_ranges), + .vsel_reg = RK818_LDO8_ON_VSEL_REG, + .vsel_mask = RK818_LDO_VSEL_MASK, + .enable_reg = RK818_LDO_EN_REG, + .enable_mask = BIT(7), + .enable_time = 400, + .owner = THIS_MODULE, + }, { + .name = "LDO_REG9", + .supply_name = "vcc9", + .id = RK818_ID_LDO9, + .ops = &rk818_reg_ops, + .type = REGULATOR_VOLTAGE, + .n_voltages = 17, + .linear_ranges = rk818_ldo_voltage_ranges, + .n_linear_ranges = ARRAY_SIZE(rk818_ldo_voltage_ranges), + .vsel_reg = RK818_BOOST_LDO9_ON_VSEL_REG, + .vsel_mask = RK818_LDO_VSEL_MASK, + .enable_reg = RK818_DCDC_EN_REG, + .enable_mask = BIT(5), + .enable_time = 400, + .owner = THIS_MODULE, + }, { + .name = "SWITCH_REG", + .supply_name = "vcc9", + .id = RK818_ID_SWITCH, + .ops = &rk818_switch_ops, + .type = REGULATOR_VOLTAGE, + .enable_reg = RK818_DCDC_EN_REG, + .enable_mask = BIT(6), + .owner = THIS_MODULE, + }, +}; + +static struct of_regulator_match rk818_reg_matches[] = { + [RK818_ID_DCDC1] = { .name = "DCDC_REG1" }, + [RK818_ID_DCDC2] = { .name = "DCDC_REG2" }, + [RK818_ID_DCDC3] = { .name = "DCDC_REG3" }, + [RK818_ID_DCDC4] = { .name = "DCDC_REG4" }, + [RK818_ID_LDO1] = { .name = "LDO_REG1" }, + [RK818_ID_LDO2] = { .name = "LDO_REG2" }, + [RK818_ID_LDO3] = { .name = "LDO_REG3" }, + [RK818_ID_LDO4] = { .name = "LDO_REG4" }, + [RK818_ID_LDO5] = { .name = "LDO_REG5" }, + [RK818_ID_LDO6] = { .name = "LDO_REG6" }, + [RK818_ID_LDO7] = { .name = "LDO_REG7" }, + [RK818_ID_LDO8] = { .name = "LDO_REG8" }, + [RK818_ID_LDO9] = { .name = "LDO_REG9" }, + [RK818_ID_SWITCH] = { .name = "SWITCH_REG" }, +}; + +static int rk818_regulator_dt_parse_pdata(struct device *dev, + struct device *client_dev, + struct regmap *map) +{ + struct device_node *np; + int ret; + + np = of_get_child_by_name(client_dev->of_node, "regulators"); + if (!np) + return -ENXIO; + + ret = of_regulator_match(dev, np, rk818_reg_matches, + RK818_NUM_REGULATORS); + + of_node_put(np); + return ret; +} + +static int rk818_regulator_probe(struct platform_device *pdev) +{ + struct rk808 *rk818 = dev_get_drvdata(pdev->dev.parent); + struct i2c_client *client = rk818->i2c; + struct regulator_config config = {}; + struct regulator_dev *rk818_rdev; + int ret, i; + + ret = rk818_regulator_dt_parse_pdata(&pdev->dev, &client->dev, + rk818->regmap); + if (ret < 0) + return ret; + + /* Instantiate the regulators */ + for (i = 0; i < RK818_NUM_REGULATORS; i++) { + if (!rk818_reg_matches[i].init_data || + !rk818_reg_matches[i].of_node) + continue; + + config.dev = &client->dev; + config.regmap = rk818->regmap; + config.of_node = rk818_reg_matches[i].of_node; + config.init_data = rk818_reg_matches[i].init_data; + + rk818_rdev = devm_regulator_register(&pdev->dev, + &rk818_reg[i], &config); + if (IS_ERR(rk818_rdev)) { + dev_err(&client->dev, + "failed to register %d regulator\n", i); + return PTR_ERR(rk818_rdev); + } + } + + return 0; +} + +static struct platform_driver rk818_regulator_driver = { + .probe = rk818_regulator_probe, + .driver = { + .name = "rk818-regulator", + .owner = THIS_MODULE, + }, +}; + +module_platform_driver(rk818_regulator_driver); + +MODULE_DESCRIPTION("regulator driver for the rk818 series PMICs"); +MODULE_AUTHOR("xsf"); +MODULE_AUTHOR("Zhang Qing"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:rk818-regulator"); + diff --git a/include/linux/mfd/rk808.h b/include/linux/mfd/rk808.h index 441b6ee72691..ffc864940ca6 100644 --- a/include/linux/mfd/rk808.h +++ b/include/linux/mfd/rk808.h @@ -47,6 +47,23 @@ enum rk808_reg { RK808_ID_SWITCH2, }; +enum rk818_reg { + RK818_ID_DCDC1, + RK818_ID_DCDC2, + RK818_ID_DCDC3, + RK818_ID_DCDC4, + RK818_ID_LDO1, + RK818_ID_LDO2, + RK818_ID_LDO3, + RK818_ID_LDO4, + RK818_ID_LDO5, + RK818_ID_LDO6, + RK818_ID_LDO7, + RK818_ID_LDO8, + RK818_ID_LDO9, + RK818_ID_SWITCH, +}; + #define RK808_SECONDS_REG 0x00 #define RK808_MINUTES_REG 0x01 #define RK808_HOURS_REG 0x02 @@ -115,6 +132,66 @@ enum rk808_reg { #define RK808_INT_STS_MSK_REG2 0x4f #define RK808_IO_POL_REG 0x50 +#define RK818_VB_MON_REG 0x21 +#define RK818_THERMAL_REG 0x22 +#define RK818_DCDC_EN_REG 0x23 +#define RK818_LDO_EN_REG 0x24 +#define RK818_SLEEP_SET_OFF_REG1 0x25 +#define RK818_SLEEP_SET_OFF_REG2 0x26 +#define RK818_DCDC_UV_STS_REG 0x27 +#define RK818_DCDC_UV_ACT_REG 0x28 +#define RK818_LDO_UV_STS_REG 0x29 +#define RK818_LDO_UV_ACT_REG 0x2a +#define RK818_DCDC_PG_REG 0x2b +#define RK818_LDO_PG_REG 0x2c +#define RK818_VOUT_MON_TDB_REG 0x2d +#define RK818_BUCK1_CONFIG_REG 0x2e +#define RK818_BUCK1_ON_VSEL_REG 0x2f +#define RK818_BUCK1_SLP_VSEL_REG 0x30 +#define RK818_BUCK2_CONFIG_REG 0x32 +#define RK818_BUCK2_ON_VSEL_REG 0x33 +#define RK818_BUCK2_SLP_VSEL_REG 0x34 +#define RK818_BUCK3_CONFIG_REG 0x36 +#define RK818_BUCK4_CONFIG_REG 0x37 +#define RK818_BUCK4_ON_VSEL_REG 0x38 +#define RK818_BUCK4_SLP_VSEL_REG 0x39 +#define RK818_BOOST_CONFIG_REG 0x3a +#define RK818_LDO1_ON_VSEL_REG 0x3b +#define RK818_LDO1_SLP_VSEL_REG 0x3c +#define RK818_LDO2_ON_VSEL_REG 0x3d +#define RK818_LDO2_SLP_VSEL_REG 0x3e +#define RK818_LDO3_ON_VSEL_REG 0x3f +#define RK818_LDO3_SLP_VSEL_REG 0x40 +#define RK818_LDO4_ON_VSEL_REG 0x41 +#define RK818_LDO4_SLP_VSEL_REG 0x42 +#define RK818_LDO5_ON_VSEL_REG 0x43 +#define RK818_LDO5_SLP_VSEL_REG 0x44 +#define RK818_LDO6_ON_VSEL_REG 0x45 +#define RK818_LDO6_SLP_VSEL_REG 0x46 +#define RK818_LDO7_ON_VSEL_REG 0x47 +#define RK818_LDO7_SLP_VSEL_REG 0x48 +#define RK818_LDO8_ON_VSEL_REG 0x49 +#define RK818_LDO8_SLP_VSEL_REG 0x4a +#define RK818_DEVCTRL_REG 0x4b +#define RK818_INT_STS_REG1 0X4c +#define RK818_INT_STS_MSK_REG1 0X4d +#define RK818_INT_STS_REG2 0X4e +#define RK818_INT_STS_MSK_REG2 0X4f +#define RK818_IO_POL_REG 0X50 +#define RK818_OTP_VDD_EN_REG 0x51 +#define RK818_H5V_EN_REG 0x52 +#define RK818_SLEEP_SET_OFF_REG3 0x53 +#define RK818_BOOST_LDO9_ON_VSEL_REG 0x54 +#define RK818_BOOST_LDO9_SLP_VSEL_REG 0x55 +#define RK818_BOOST_CTRL_REG 0x56 +#define RK818_DCDC_ILMAX_REG 0x90 +#define RK818_CHRG_COMP_REG 0x9a +#define RK818_SUP_STS_REG 0xa0 +#define RK818_USB_CTRL_REG 0xa1 + +#define RK818_SAVE_DATA19 0xF2 +#define RK818_NUM_REGULATORS 14 + /* IRQ Definitions */ #define RK808_IRQ_VOUT_LO 0 #define RK808_IRQ_VB_LO 1 @@ -168,6 +245,128 @@ enum rk808_reg { #define VOUT_LO_INT BIT(0) #define CLK32KOUT2_EN BIT(0) +#define H5V_EN_MASK BIT(0) +#define H5V_EN_ENABLE BIT(0) +#define REF_RDY_CTRL_MASK BIT(1) +#define REF_RDY_CTRL_ENABLE BIT(1) + +/*RK818_DCDC_EN_REG*/ +#define BUCK1_EN_MASK BIT(0) +#define BUCK2_EN_MASK BIT(1) +#define BUCK3_EN_MASK BIT(2) +#define BUCK4_EN_MASK BIT(3) +#define BOOST_EN_MASK BIT(4) +#define LDO9_EN_MASK BIT(5) +#define SWITCH_EN_MASK BIT(6) +#define OTG_EN_MASK BIT(7) + +#define BUCK1_EN_ENABLE BIT(0) +#define BUCK2_EN_ENABLE BIT(1) +#define BUCK3_EN_ENABLE BIT(2) +#define BUCK4_EN_ENABLE BIT(3) +#define BOOST_EN_ENABLE BIT(4) +#define LDO9_EN_ENABLE BIT(5) +#define SWITCH_EN_ENABLE BIT(6) +#define OTG_EN_ENABLE BIT(7) + +/* IRQ Definitions */ +#define RK818_IRQ_VOUT_LO 0 +#define RK818_IRQ_VB_LO 1 +#define RK818_IRQ_PWRON 2 +#define RK818_IRQ_PWRON_LP 3 +#define RK818_IRQ_HOTDIE 4 +#define RK818_IRQ_RTC_ALARM 5 +#define RK818_IRQ_RTC_PERIOD 6 +#define RK818_IRQ_USB_OV 7 +#define RK818_IRQ_PLUG_IN 8 +#define RK818_IRQ_PLUG_OUT 9 +#define RK818_IRQ_CHG_OK 10 +#define RK818_IRQ_CHG_TE 11 +#define RK818_IRQ_CHG_TS1 12 +#define RK818_IRQ_TS2 13 +#define RK818_IRQ_CHG_CVTLIM 14 +#define RK818_IRQ_DISCHG_ILIM 15 + +#define BUCK1_SLP_SET_MASK BIT(0) +#define BUCK2_SLP_SET_MASK BIT(1) +#define BUCK3_SLP_SET_MASK BIT(2) +#define BUCK4_SLP_SET_MASK BIT(3) +#define BOOST_SLP_SET_MASK BIT(4) +#define LDO9_SLP_SET_MASK BIT(5) +#define SWITCH_SLP_SET_MASK BIT(6) +#define OTG_SLP_SET_MASK BIT(7) + +#define BUCK1_SLP_SET_OFF BIT(0) +#define BUCK2_SLP_SET_OFF BIT(1) +#define BUCK3_SLP_SET_OFF BIT(2) +#define BUCK4_SLP_SET_OFF BIT(3) +#define BOOST_SLP_SET_OFF BIT(4) +#define LDO9_SLP_SET_OFF BIT(5) +#define SWITCH_SLP_SET_OFF BIT(6) +#define OTG_SLP_SET_OFF BIT(7) + +#define BUCK1_SLP_SET_ON BIT(0) +#define BUCK2_SLP_SET_ON BIT(1) +#define BUCK3_SLP_SET_ON BIT(2) +#define BUCK4_SLP_SET_ON BIT(3) +#define BOOST_SLP_SET_ON BIT(4) +#define LDO9_SLP_SET_ON BIT(5) +#define SWITCH_SLP_SET_ON BIT(6) +#define OTG_SLP_SET_ON BIT(7) + +#define VOUT_LO_MASK BIT(0) +#define VB_LO_MASK BIT(1) +#define PWRON_MASK BIT(2) +#define PWRON_LP_MASK BIT(3) +#define HOTDIE_MASK BIT(4) +#define RTC_ALARM_MASK BIT(5) +#define RTC_PERIOD_MASK BIT(6) +#define USB_OV_MASK BIT(7) + +#define VOUT_LO_DISABLE BIT(0) +#define VB_LO_DISABLE BIT(1) +#define PWRON_DISABLE BIT(2) +#define PWRON_LP_DISABLE BIT(3) +#define HOTDIE_DISABLE BIT(4) +#define RTC_ALARM_DISABLE BIT(5) +#define RTC_PERIOD_DISABLE BIT(6) +#define USB_OV_INT_DISABLE BIT(7) + +#define VOUT_LO_ENABLE (0 << 0) +#define VB_LO_ENABLE (0 << 1) +#define PWRON_ENABLE (0 << 2) +#define PWRON_LP_ENABLE (0 << 3) +#define HOTDIE_ENABLE (0 << 4) +#define RTC_ALARM_ENABLE (0 << 5) +#define RTC_PERIOD_ENABLE (0 << 6) +#define USB_OV_INT_ENABLE (0 << 7) + +#define PLUG_IN_MASK BIT(0) +#define PLUG_OUT_MASK BIT(1) +#define CHGOK_MASK BIT(2) +#define CHGTE_MASK BIT(3) +#define CHGTS1_MASK BIT(4) +#define TS2_MASK BIT(5) +#define CHG_CVTLIM_MASK BIT(6) +#define DISCHG_ILIM_MASK BIT(7) + +#define PLUG_IN_DISABLE BIT(0) +#define PLUG_OUT_DISABLE BIT(1) +#define CHGOK_DISABLE BIT(2) +#define CHGTE_DISABLE BIT(3) +#define CHGTS1_DISABLE BIT(4) +#define TS2_DISABLE BIT(5) +#define CHG_CVTLIM_DISABLE BIT(6) +#define DISCHG_ILIM_DISABLE BIT(7) + +#define PLUG_IN_ENABLE BIT(0) +#define PLUG_OUT_ENABLE BIT(1) +#define CHGOK_ENABLE BIT(2) +#define CHGTE_ENABLE BIT(3) +#define CHGTS1_ENABLE BIT(4) +#define TS2_ENABLE BIT(5) +#define CHG_CVTLIM_ENABLE BIT(6) +#define DISCHG_ILIM_ENABLE BIT(7) enum { BUCK_ILMIN_50MA, -- 2.34.1