From patchwork Tue Mar 7 15:36:08 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sebastian Reichel X-Patchwork-Id: 660055 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 2487FC6FD1A for ; Tue, 7 Mar 2023 15:36:37 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230310AbjCGPgg (ORCPT ); Tue, 7 Mar 2023 10:36:36 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:37254 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229991AbjCGPge (ORCPT ); Tue, 7 Mar 2023 10:36:34 -0500 Received: from madras.collabora.co.uk (madras.collabora.co.uk [46.235.227.172]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 484563CE3C; Tue, 7 Mar 2023 07:36:23 -0800 (PST) Received: from jupiter.universe (dyndsl-091-248-189-073.ewe-ip-backbone.de [91.248.189.73]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) (Authenticated sender: sre) by madras.collabora.co.uk (Postfix) with ESMTPSA id 1694F6602ED2; Tue, 7 Mar 2023 15:36:21 +0000 (GMT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=collabora.com; s=mail; t=1678203381; bh=OMM+Hhvb7MWnFu7IHCuZ6ekNvvROiGqSsjlCrcGP0R4=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=FGbddEDiSJ8QmOscn7ARI/kesqr8yoHiBwraEiFkcMRpk40gTl0y0+H/KxUxBsj5+ ISXzfeW1zgZxEEZ1Kd+ceQHXB60+1ixLDEUfYuGZJWY7DPnQNkWXdRG+aMFoluxYzK giP3zVFDbR3e/nXunIJOuAxlV1m5F/JDi+vT/cZzjmbGZztzQ163NkFGDMMM8T1LX7 39R5FGSHcmr6mpiqUZAr93C3GQKfQWJdPg4EBcng1Equg47qYhDZbPLTzYX1KReGfX JJNkZAHKDxvL9k8/m0nAwzePXOc/iLEVNAyo8B1DS1/YnyWv70wIlsFhu/jzFCGyXL sitCX135zULsg== Received: by jupiter.universe (Postfix, from userid 1000) id 2194A480117; Tue, 7 Mar 2023 16:36:19 +0100 (CET) From: Sebastian Reichel To: Heiko Stuebner , Rob Herring , Krzysztof Kozlowski , Lee Jones Cc: Michael Turquette , Stephen Boyd , Linus Walleij , Mark Brown , Liam Girdwood , Alexandre Belloni , Alessandro Zummo , linux-rockchip@lists.infradead.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, Sebastian Reichel , kernel@collabora.com Subject: [PATCHv7 02/11] mfd: rk808: convert to device managed resources Date: Tue, 7 Mar 2023 16:36:08 +0100 Message-Id: <20230307153617.643260-3-sebastian.reichel@collabora.com> X-Mailer: git-send-email 2.39.2 In-Reply-To: <20230307153617.643260-1-sebastian.reichel@collabora.com> References: <20230307153617.643260-1-sebastian.reichel@collabora.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: devicetree@vger.kernel.org Fully convert the driver to device managed resources. Acked-for-MFD-by: Lee Jones Signed-off-by: Sebastian Reichel --- drivers/mfd/rk808.c | 64 ++++++++++++++++----------------------------- 1 file changed, 22 insertions(+), 42 deletions(-) diff --git a/drivers/mfd/rk808.c b/drivers/mfd/rk808.c index 0f22ef61e817..a996a43f9204 100644 --- a/drivers/mfd/rk808.c +++ b/drivers/mfd/rk808.c @@ -548,13 +548,11 @@ static const struct regmap_irq_chip rk818_irq_chip = { .init_ack_masked = true, }; -static struct i2c_client *rk808_i2c_client; - -static void rk808_pm_power_off(void) +static int rk808_power_off(struct sys_off_data *data) { + struct rk808 *rk808 = data->cb_data; int ret; unsigned int reg, bit; - struct rk808 *rk808 = i2c_get_clientdata(rk808_i2c_client); switch (rk808->variant) { case RK805_ID: @@ -575,16 +573,18 @@ static void rk808_pm_power_off(void) bit = DEV_OFF; break; default: - return; + return NOTIFY_DONE; } ret = regmap_update_bits(rk808->regmap, reg, bit, bit); if (ret) - dev_err(&rk808_i2c_client->dev, "Failed to shutdown device!\n"); + dev_err(&rk808->i2c->dev, "Failed to shutdown device!\n"); + + return NOTIFY_DONE; } -static int rk808_restart_notify(struct notifier_block *this, unsigned long mode, void *cmd) +static int rk808_restart(struct sys_off_data *data) { - struct rk808 *rk808 = i2c_get_clientdata(rk808_i2c_client); + struct rk808 *rk808 = data->cb_data; unsigned int reg, bit; int ret; @@ -600,16 +600,11 @@ static int rk808_restart_notify(struct notifier_block *this, unsigned long mode, } ret = regmap_update_bits(rk808->regmap, reg, bit, bit); if (ret) - dev_err(&rk808_i2c_client->dev, "Failed to restart device!\n"); + dev_err(&rk808->i2c->dev, "Failed to restart device!\n"); return NOTIFY_DONE; } -static struct notifier_block rk808_restart_handler = { - .notifier_call = rk808_restart_notify, - .priority = 192, -}; - static void rk8xx_shutdown(struct i2c_client *client) { struct rk808 *rk808 = i2c_get_clientdata(client); @@ -745,9 +740,9 @@ static int rk808_probe(struct i2c_client *client) return -EINVAL; } - ret = regmap_add_irq_chip(rk808->regmap, client->irq, - IRQF_ONESHOT, -1, - rk808->regmap_irq_chip, &rk808->irq_data); + ret = devm_regmap_add_irq_chip(&client->dev, rk808->regmap, client->irq, + IRQF_ONESHOT, -1, + rk808->regmap_irq_chip, &rk808->irq_data); if (ret) { dev_err(&client->dev, "Failed to add irq_chip %d\n", ret); return ret; @@ -771,17 +766,23 @@ static int rk808_probe(struct i2c_client *client) regmap_irq_get_domain(rk808->irq_data)); if (ret) { dev_err(&client->dev, "failed to add MFD devices %d\n", ret); - goto err_irq; + return ret; } if (of_property_read_bool(np, "rockchip,system-power-controller")) { - rk808_i2c_client = client; - pm_power_off = rk808_pm_power_off; + ret = devm_register_sys_off_handler(&client->dev, + SYS_OFF_MODE_POWER_OFF_PREPARE, SYS_OFF_PRIO_HIGH, + &rk808_power_off, rk808); + if (ret) + return dev_err_probe(&client->dev, ret, + "failed to register poweroff handler\n"); switch (rk808->variant) { case RK809_ID: case RK817_ID: - ret = register_restart_handler(&rk808_restart_handler); + ret = devm_register_sys_off_handler(&client->dev, + SYS_OFF_MODE_RESTART, SYS_OFF_PRIO_HIGH, + &rk808_restart, rk808); if (ret) dev_warn(&client->dev, "failed to register rst handler, %d\n", ret); break; @@ -792,26 +793,6 @@ static int rk808_probe(struct i2c_client *client) } return 0; - -err_irq: - regmap_del_irq_chip(client->irq, rk808->irq_data); - return ret; -} - -static void rk808_remove(struct i2c_client *client) -{ - struct rk808 *rk808 = i2c_get_clientdata(client); - - regmap_del_irq_chip(client->irq, rk808->irq_data); - - /** - * pm_power_off may points to a function from another module. - * Check if the pointer is set by us and only then overwrite it. - */ - if (pm_power_off == rk808_pm_power_off) - pm_power_off = NULL; - - unregister_restart_handler(&rk808_restart_handler); } static int __maybe_unused rk8xx_suspend(struct device *dev) @@ -868,7 +849,6 @@ static struct i2c_driver rk808_i2c_driver = { .pm = &rk8xx_pm_ops, }, .probe_new = rk808_probe, - .remove = rk808_remove, .shutdown = rk8xx_shutdown, }; From patchwork Tue Mar 7 15:36:11 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sebastian Reichel X-Patchwork-Id: 660052 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 701C9C678D5 for ; Tue, 7 Mar 2023 15:36:53 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231375AbjCGPgv (ORCPT ); Tue, 7 Mar 2023 10:36:51 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:38160 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231346AbjCGPgp (ORCPT ); Tue, 7 Mar 2023 10:36:45 -0500 Received: from madras.collabora.co.uk (madras.collabora.co.uk [IPv6:2a00:1098:0:82:1000:25:2eeb:e5ab]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id EC5F065AC; Tue, 7 Mar 2023 07:36:34 -0800 (PST) Received: from jupiter.universe (dyndsl-091-248-189-073.ewe-ip-backbone.de [91.248.189.73]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits)) (No client certificate requested) (Authenticated sender: sre) by madras.collabora.co.uk (Postfix) with ESMTPSA id 9E0286602FE8; Tue, 7 Mar 2023 15:36:23 +0000 (GMT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=collabora.com; s=mail; t=1678203383; bh=Uralss2iRODFklFq+VlpAnBBM3s2BAk+zOFv0yWYOxE=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=UKnxmMUuISIy8Q6c7Ap0qupJ7RH+e/MHbEWHWasat/Y3IFeXRqpO0kQD9YvRFObBZ +6lbLnCaYZ6qn/bETuUePszClcttqjSR73MSpXOQdGIaKzWZEdcCJ64o1jtgkwKnNm RuNHFLjXE4fhnkK7eDf8F1155PbAx66fV7dQLAzZSBvxJRYmnpvuedsMfCvCIfn0CV QAd1ZTrb+T4Q0CybNd8tKSH5zLGO8GKVW4ltEjRy2uSsLN2qsDvF5hjsXB9hV77Nm1 84YRHw7WKJ3MwlqNVByvhptNqwjSHMCNPB+onPLZGRWnQMiIcNlqtXVsAyM7ZhD/Pn LYf+Q5+AioVkw== Received: by jupiter.universe (Postfix, from userid 1000) id 299AA48011D; Tue, 7 Mar 2023 16:36:19 +0100 (CET) From: Sebastian Reichel To: Heiko Stuebner , Rob Herring , Krzysztof Kozlowski , Lee Jones Cc: Michael Turquette , Stephen Boyd , Linus Walleij , Mark Brown , Liam Girdwood , Alexandre Belloni , Alessandro Zummo , linux-rockchip@lists.infradead.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, Sebastian Reichel , kernel@collabora.com Subject: [PATCHv7 05/11] mfd: rk808: split into core and i2c Date: Tue, 7 Mar 2023 16:36:11 +0100 Message-Id: <20230307153617.643260-6-sebastian.reichel@collabora.com> X-Mailer: git-send-email 2.39.2 In-Reply-To: <20230307153617.643260-1-sebastian.reichel@collabora.com> References: <20230307153617.643260-1-sebastian.reichel@collabora.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: devicetree@vger.kernel.org Split rk808 into a core and an i2c part in preperation for SPI support. Acked-for-MFD-by: Lee Jones Signed-off-by: Sebastian Reichel --- drivers/clk/Kconfig | 2 +- drivers/input/misc/Kconfig | 2 +- drivers/mfd/Kconfig | 7 +- drivers/mfd/Makefile | 3 +- drivers/mfd/{rk808.c => rk8xx-core.c} | 209 +++++--------------------- drivers/mfd/rk8xx-i2c.c | 200 ++++++++++++++++++++++++ drivers/pinctrl/Kconfig | 2 +- drivers/power/supply/Kconfig | 2 +- drivers/regulator/Kconfig | 2 +- drivers/rtc/Kconfig | 2 +- include/linux/mfd/rk808.h | 6 + sound/soc/codecs/Kconfig | 2 +- 12 files changed, 256 insertions(+), 183 deletions(-) rename drivers/mfd/{rk808.c => rk8xx-core.c} (76%) create mode 100644 drivers/mfd/rk8xx-i2c.c diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig index b6c5bf69a2b2..b08fa3273c84 100644 --- a/drivers/clk/Kconfig +++ b/drivers/clk/Kconfig @@ -82,7 +82,7 @@ config COMMON_CLK_MAX9485 config COMMON_CLK_RK808 tristate "Clock driver for RK805/RK808/RK809/RK817/RK818" - depends on MFD_RK808 + depends on MFD_RK8XX help This driver supports RK805, RK809 and RK817, RK808 and RK818 crystal oscillator clock. These multi-function devices have two fixed-rate oscillators, clocked at 32KHz each. diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig index 5c2d0c06d2a5..6a6978fc68fa 100644 --- a/drivers/input/misc/Kconfig +++ b/drivers/input/misc/Kconfig @@ -598,7 +598,7 @@ config INPUT_PWM_VIBRA config INPUT_RK805_PWRKEY tristate "Rockchip RK805 PMIC power key support" - depends on MFD_RK808 + depends on MFD_RK8XX help Select this option to enable power key driver for RK805. diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index fcc141e067b9..2998d04f8756 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -1176,12 +1176,17 @@ config MFD_RC5T583 Additional drivers must be enabled in order to use the different functionality of the device. -config MFD_RK808 +config MFD_RK8XX + bool + select MFD_CORE + +config MFD_RK8XX_I2C tristate "Rockchip RK805/RK808/RK809/RK817/RK818 Power Management Chip" depends on I2C && OF select MFD_CORE select REGMAP_I2C select REGMAP_IRQ + select MFD_RK8XX help If you say yes here you get support for the RK805, RK808, RK809, RK817 and RK818 Power Management chips. diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile index 2f6c89d1e277..be9e4806d2e6 100644 --- a/drivers/mfd/Makefile +++ b/drivers/mfd/Makefile @@ -213,7 +213,8 @@ obj-$(CONFIG_MFD_PALMAS) += palmas.o obj-$(CONFIG_MFD_VIPERBOARD) += viperboard.o obj-$(CONFIG_MFD_NTXEC) += ntxec.o obj-$(CONFIG_MFD_RC5T583) += rc5t583.o rc5t583-irq.o -obj-$(CONFIG_MFD_RK808) += rk808.o +obj-$(CONFIG_MFD_RK8XX) += rk8xx-core.o +obj-$(CONFIG_MFD_RK8XX_I2C) += rk8xx-i2c.o obj-$(CONFIG_MFD_RN5T618) += rn5t618.o obj-$(CONFIG_MFD_SEC_CORE) += sec-core.o sec-irq.o obj-$(CONFIG_MFD_SYSCON) += syscon.o diff --git a/drivers/mfd/rk808.c b/drivers/mfd/rk8xx-core.c similarity index 76% rename from drivers/mfd/rk808.c rename to drivers/mfd/rk8xx-core.c index ce52307cbaea..5c0a5acef34c 100644 --- a/drivers/mfd/rk808.c +++ b/drivers/mfd/rk8xx-core.c @@ -1,18 +1,15 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * MFD core driver for Rockchip RK808/RK818 + * MFD core driver for Rockchip RK8XX * * Copyright (c) 2014, Fuzhou Rockchip Electronics Co., Ltd + * Copyright (C) 2016 PHYTEC Messtechnik GmbH * * Author: Chris Zhong * Author: Zhang Qing - * - * Copyright (C) 2016 PHYTEC Messtechnik GmbH - * * Author: Wadim Egorov */ -#include #include #include #include @@ -27,92 +24,6 @@ struct rk808_reg_data { int value; }; -static bool rk808_is_volatile_reg(struct device *dev, unsigned int reg) -{ - /* - * Notes: - * - Technically the ROUND_30s bit makes RTC_CTRL_REG volatile, but - * we don't use that feature. It's better to cache. - * - It's unlikely we care that RK808_DEVCTRL_REG is volatile since - * bits are cleared in case when we shutoff anyway, but better safe. - */ - - switch (reg) { - case RK808_SECONDS_REG ... RK808_WEEKS_REG: - case RK808_RTC_STATUS_REG: - case RK808_VB_MON_REG: - case RK808_THERMAL_REG: - case RK808_DCDC_UV_STS_REG: - case RK808_LDO_UV_STS_REG: - case RK808_DCDC_PG_REG: - case RK808_LDO_PG_REG: - case RK808_DEVCTRL_REG: - case RK808_INT_STS_REG1: - case RK808_INT_STS_REG2: - return true; - } - - return false; -} - -static bool rk817_is_volatile_reg(struct device *dev, unsigned int reg) -{ - /* - * Notes: - * - Technically the ROUND_30s bit makes RTC_CTRL_REG volatile, but - * we don't use that feature. It's better to cache. - */ - - switch (reg) { - case RK817_SECONDS_REG ... RK817_WEEKS_REG: - case RK817_RTC_STATUS_REG: - case RK817_CODEC_DTOP_LPT_SRST: - case RK817_GAS_GAUGE_ADC_CONFIG0 ... RK817_GAS_GAUGE_CUR_ADC_K0: - case RK817_PMIC_CHRG_STS: - case RK817_PMIC_CHRG_OUT: - case RK817_PMIC_CHRG_IN: - case RK817_INT_STS_REG0: - case RK817_INT_STS_REG1: - case RK817_INT_STS_REG2: - case RK817_SYS_STS: - return true; - } - - return false; -} - -static const struct regmap_config rk818_regmap_config = { - .reg_bits = 8, - .val_bits = 8, - .max_register = RK818_USB_CTRL_REG, - .cache_type = REGCACHE_RBTREE, - .volatile_reg = rk808_is_volatile_reg, -}; - -static const struct regmap_config rk805_regmap_config = { - .reg_bits = 8, - .val_bits = 8, - .max_register = RK805_OFF_SOURCE_REG, - .cache_type = REGCACHE_RBTREE, - .volatile_reg = rk808_is_volatile_reg, -}; - -static const struct regmap_config rk808_regmap_config = { - .reg_bits = 8, - .val_bits = 8, - .max_register = RK808_IO_POL_REG, - .cache_type = REGCACHE_RBTREE, - .volatile_reg = rk808_is_volatile_reg, -}; - -static const struct regmap_config rk817_regmap_config = { - .reg_bits = 8, - .val_bits = 8, - .max_register = RK817_GPIO_INT_CFG, - .cache_type = REGCACHE_NONE, - .volatile_reg = rk817_is_volatile_reg, -}; - static const struct resource rtc_resources[] = { DEFINE_RES_IRQ(RK808_IRQ_RTC_ALARM), }; @@ -605,9 +516,9 @@ static int rk808_restart(struct sys_off_data *data) return NOTIFY_DONE; } -static void rk8xx_shutdown(struct i2c_client *client) +void rk8xx_shutdown(struct device *dev) { - struct rk808 *rk808 = i2c_get_clientdata(client); + struct rk808 *rk808 = dev_get_drvdata(dev); int ret; switch (rk808->variant) { @@ -628,61 +539,31 @@ static void rk8xx_shutdown(struct i2c_client *client) return; } if (ret) - dev_warn(&client->dev, + dev_warn(dev, "Cannot switch to power down function\n"); } +EXPORT_SYMBOL_GPL(rk8xx_shutdown); -static const struct of_device_id rk808_of_match[] = { - { .compatible = "rockchip,rk805" }, - { .compatible = "rockchip,rk808" }, - { .compatible = "rockchip,rk809" }, - { .compatible = "rockchip,rk817" }, - { .compatible = "rockchip,rk818" }, - { }, -}; -MODULE_DEVICE_TABLE(of, rk808_of_match); - -static int rk808_probe(struct i2c_client *client) +int rk8xx_probe(struct device *dev, int variant, unsigned int irq, struct regmap *regmap) { - struct device_node *np = client->dev.of_node; struct rk808 *rk808; const struct rk808_reg_data *pre_init_reg; const struct mfd_cell *cells; int nr_pre_init_regs; int nr_cells; - int msb, lsb; - unsigned char pmic_id_msb, pmic_id_lsb; int ret; int i; - rk808 = devm_kzalloc(&client->dev, sizeof(*rk808), GFP_KERNEL); + rk808 = devm_kzalloc(dev, sizeof(*rk808), GFP_KERNEL); if (!rk808) return -ENOMEM; - - if (of_device_is_compatible(np, "rockchip,rk817") || - of_device_is_compatible(np, "rockchip,rk809")) { - pmic_id_msb = RK817_ID_MSB; - pmic_id_lsb = RK817_ID_LSB; - } else { - pmic_id_msb = RK808_ID_MSB; - pmic_id_lsb = RK808_ID_LSB; - } - - /* Read chip variant */ - msb = i2c_smbus_read_byte_data(client, pmic_id_msb); - if (msb < 0) - return dev_err_probe(&client->dev, msb, "failed to read the chip id MSB\n"); - - lsb = i2c_smbus_read_byte_data(client, pmic_id_lsb); - if (lsb < 0) - return dev_err_probe(&client->dev, lsb, "failed to read the chip id LSB\n"); - - rk808->variant = ((msb << 8) | lsb) & RK8XX_ID_MSK; - dev_info(&client->dev, "chip id: 0x%x\n", (unsigned int)rk808->variant); + rk808->dev = dev; + rk808->variant = variant; + rk808->regmap = regmap; + dev_set_drvdata(dev, rk808); switch (rk808->variant) { case RK805_ID: - rk808->regmap_cfg = &rk805_regmap_config; rk808->regmap_irq_chip = &rk805_irq_chip; pre_init_reg = rk805_pre_init_reg; nr_pre_init_regs = ARRAY_SIZE(rk805_pre_init_reg); @@ -690,7 +571,6 @@ static int rk808_probe(struct i2c_client *client) nr_cells = ARRAY_SIZE(rk805s); break; case RK808_ID: - rk808->regmap_cfg = &rk808_regmap_config; rk808->regmap_irq_chip = &rk808_irq_chip; pre_init_reg = rk808_pre_init_reg; nr_pre_init_regs = ARRAY_SIZE(rk808_pre_init_reg); @@ -698,7 +578,6 @@ static int rk808_probe(struct i2c_client *client) nr_cells = ARRAY_SIZE(rk808s); break; case RK818_ID: - rk808->regmap_cfg = &rk818_regmap_config; rk808->regmap_irq_chip = &rk818_irq_chip; pre_init_reg = rk818_pre_init_reg; nr_pre_init_regs = ARRAY_SIZE(rk818_pre_init_reg); @@ -707,7 +586,6 @@ static int rk808_probe(struct i2c_client *client) break; case RK809_ID: case RK817_ID: - rk808->regmap_cfg = &rk817_regmap_config; rk808->regmap_irq_chip = &rk817_irq_chip; pre_init_reg = rk817_pre_init_reg; nr_pre_init_regs = ARRAY_SIZE(rk817_pre_init_reg); @@ -715,27 +593,20 @@ static int rk808_probe(struct i2c_client *client) nr_cells = ARRAY_SIZE(rk817s); break; default: - dev_err(&client->dev, "Unsupported RK8XX ID %lu\n", - rk808->variant); + dev_err(dev, "Unsupported RK8XX ID %lu\n", rk808->variant); return -EINVAL; } - rk808->dev = &client->dev; - i2c_set_clientdata(client, rk808); - - rk808->regmap = devm_regmap_init_i2c(client, rk808->regmap_cfg); - if (IS_ERR(rk808->regmap)) - return dev_err_probe(&client->dev, PTR_ERR(rk808->regmap), - "regmap initialization failed\n"); + dev_info(dev, "chip id: 0x%x\n", (unsigned int)rk808->variant); - if (!client->irq) - return dev_err_probe(&client->dev, -EINVAL, "No interrupt support, no core IRQ\n"); + if (!irq) + return dev_err_probe(dev, -EINVAL, "No interrupt support, no core IRQ\n"); - ret = devm_regmap_add_irq_chip(&client->dev, rk808->regmap, client->irq, + ret = devm_regmap_add_irq_chip(dev, rk808->regmap, irq, IRQF_ONESHOT, -1, rk808->regmap_irq_chip, &rk808->irq_data); if (ret) - return dev_err_probe(&client->dev, ret, "Failed to add irq_chip\n"); + return dev_err_probe(dev, ret, "Failed to add irq_chip\n"); for (i = 0; i < nr_pre_init_regs; i++) { ret = regmap_update_bits(rk808->regmap, @@ -743,45 +614,46 @@ static int rk808_probe(struct i2c_client *client) pre_init_reg[i].mask, pre_init_reg[i].value); if (ret) - return dev_err_probe(&client->dev, ret, "0x%x write err\n", + return dev_err_probe(dev, ret, "0x%x write err\n", pre_init_reg[i].addr); } - ret = devm_mfd_add_devices(&client->dev, PLATFORM_DEVID_NONE, + ret = devm_mfd_add_devices(dev, PLATFORM_DEVID_NONE, cells, nr_cells, NULL, 0, regmap_irq_get_domain(rk808->irq_data)); if (ret) - return dev_err_probe(&client->dev, ret, "failed to add MFD devices\n"); + return dev_err_probe(dev, ret, "failed to add MFD devices\n"); - if (of_property_read_bool(np, "rockchip,system-power-controller")) { - ret = devm_register_sys_off_handler(&client->dev, + if (device_property_read_bool(dev, "rockchip,system-power-controller")) { + ret = devm_register_sys_off_handler(dev, SYS_OFF_MODE_POWER_OFF_PREPARE, SYS_OFF_PRIO_HIGH, &rk808_power_off, rk808); if (ret) - return dev_err_probe(&client->dev, ret, + return dev_err_probe(dev, ret, "failed to register poweroff handler\n"); switch (rk808->variant) { case RK809_ID: case RK817_ID: - ret = devm_register_sys_off_handler(&client->dev, + ret = devm_register_sys_off_handler(dev, SYS_OFF_MODE_RESTART, SYS_OFF_PRIO_HIGH, &rk808_restart, rk808); if (ret) - dev_warn(&client->dev, "failed to register rst handler, %d\n", ret); + dev_warn(dev, "failed to register rst handler, %d\n", ret); break; default: - dev_dbg(&client->dev, "pmic controlled board reset not supported\n"); + dev_dbg(dev, "pmic controlled board reset not supported\n"); break; } } return 0; } +EXPORT_SYMBOL_GPL(rk8xx_probe); -static int __maybe_unused rk8xx_suspend(struct device *dev) +int rk8xx_suspend(struct device *dev) { - struct rk808 *rk808 = i2c_get_clientdata(to_i2c_client(dev)); + struct rk808 *rk808 = dev_get_drvdata(dev); int ret = 0; switch (rk808->variant) { @@ -804,10 +676,11 @@ static int __maybe_unused rk8xx_suspend(struct device *dev) return ret; } +EXPORT_SYMBOL_GPL(rk8xx_suspend); -static int __maybe_unused rk8xx_resume(struct device *dev) +int rk8xx_resume(struct device *dev) { - struct rk808 *rk808 = i2c_get_clientdata(to_i2c_client(dev)); + struct rk808 *rk808 = dev_get_drvdata(dev); int ret = 0; switch (rk808->variant) { @@ -824,22 +697,10 @@ static int __maybe_unused rk8xx_resume(struct device *dev) return ret; } -static SIMPLE_DEV_PM_OPS(rk8xx_pm_ops, rk8xx_suspend, rk8xx_resume); - -static struct i2c_driver rk808_i2c_driver = { - .driver = { - .name = "rk808", - .of_match_table = rk808_of_match, - .pm = &rk8xx_pm_ops, - }, - .probe_new = rk808_probe, - .shutdown = rk8xx_shutdown, -}; - -module_i2c_driver(rk808_i2c_driver); +EXPORT_SYMBOL_GPL(rk8xx_resume); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Chris Zhong "); MODULE_AUTHOR("Zhang Qing "); MODULE_AUTHOR("Wadim Egorov "); -MODULE_DESCRIPTION("RK808/RK818 PMIC driver"); +MODULE_DESCRIPTION("RK8xx PMIC core"); diff --git a/drivers/mfd/rk8xx-i2c.c b/drivers/mfd/rk8xx-i2c.c new file mode 100644 index 000000000000..6d121b589fec --- /dev/null +++ b/drivers/mfd/rk8xx-i2c.c @@ -0,0 +1,200 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Rockchip RK808/RK818 Core (I2C) driver + * + * Copyright (c) 2014, Fuzhou Rockchip Electronics Co., Ltd + * Copyright (C) 2016 PHYTEC Messtechnik GmbH + * + * Author: Chris Zhong + * Author: Zhang Qing + * Author: Wadim Egorov + */ + +#include +#include +#include +#include +#include + +static bool rk808_is_volatile_reg(struct device *dev, unsigned int reg) +{ + /* + * Notes: + * - Technically the ROUND_30s bit makes RTC_CTRL_REG volatile, but + * we don't use that feature. It's better to cache. + * - It's unlikely we care that RK808_DEVCTRL_REG is volatile since + * bits are cleared in case when we shutoff anyway, but better safe. + */ + + switch (reg) { + case RK808_SECONDS_REG ... RK808_WEEKS_REG: + case RK808_RTC_STATUS_REG: + case RK808_VB_MON_REG: + case RK808_THERMAL_REG: + case RK808_DCDC_UV_STS_REG: + case RK808_LDO_UV_STS_REG: + case RK808_DCDC_PG_REG: + case RK808_LDO_PG_REG: + case RK808_DEVCTRL_REG: + case RK808_INT_STS_REG1: + case RK808_INT_STS_REG2: + return true; + } + + return false; +} + +static bool rk817_is_volatile_reg(struct device *dev, unsigned int reg) +{ + /* + * Notes: + * - Technically the ROUND_30s bit makes RTC_CTRL_REG volatile, but + * we don't use that feature. It's better to cache. + */ + + switch (reg) { + case RK817_SECONDS_REG ... RK817_WEEKS_REG: + case RK817_RTC_STATUS_REG: + case RK817_CODEC_DTOP_LPT_SRST: + case RK817_GAS_GAUGE_ADC_CONFIG0 ... RK817_GAS_GAUGE_CUR_ADC_K0: + case RK817_PMIC_CHRG_STS: + case RK817_PMIC_CHRG_OUT: + case RK817_PMIC_CHRG_IN: + case RK817_INT_STS_REG0: + case RK817_INT_STS_REG1: + case RK817_INT_STS_REG2: + case RK817_SYS_STS: + return true; + } + + return false; +} + + +static const struct regmap_config rk818_regmap_config = { + .reg_bits = 8, + .val_bits = 8, + .max_register = RK818_USB_CTRL_REG, + .cache_type = REGCACHE_RBTREE, + .volatile_reg = rk808_is_volatile_reg, +}; + +static const struct regmap_config rk805_regmap_config = { + .reg_bits = 8, + .val_bits = 8, + .max_register = RK805_OFF_SOURCE_REG, + .cache_type = REGCACHE_RBTREE, + .volatile_reg = rk808_is_volatile_reg, +}; + +static const struct regmap_config rk808_regmap_config = { + .reg_bits = 8, + .val_bits = 8, + .max_register = RK808_IO_POL_REG, + .cache_type = REGCACHE_RBTREE, + .volatile_reg = rk808_is_volatile_reg, +}; + +static const struct regmap_config rk817_regmap_config = { + .reg_bits = 8, + .val_bits = 8, + .max_register = RK817_GPIO_INT_CFG, + .cache_type = REGCACHE_NONE, + .volatile_reg = rk817_is_volatile_reg, +}; + +static int rk8xx_i2c_get_variant(struct i2c_client *client) +{ + u8 pmic_id_msb, pmic_id_lsb; + int msb, lsb; + + if (of_device_is_compatible(client->dev.of_node, "rockchip,rk817") || + of_device_is_compatible(client->dev.of_node, "rockchip,rk809")) { + pmic_id_msb = RK817_ID_MSB; + pmic_id_lsb = RK817_ID_LSB; + } else { + pmic_id_msb = RK808_ID_MSB; + pmic_id_lsb = RK808_ID_LSB; + } + + /* Read chip variant */ + msb = i2c_smbus_read_byte_data(client, pmic_id_msb); + if (msb < 0) + return dev_err_probe(&client->dev, msb, "failed to read the chip id MSB\n"); + + lsb = i2c_smbus_read_byte_data(client, pmic_id_lsb); + if (lsb < 0) + return dev_err_probe(&client->dev, lsb, "failed to read the chip id LSB\n"); + + return ((msb << 8) | lsb) & RK8XX_ID_MSK; +} + +static int rk8xx_i2c_probe(struct i2c_client *client) +{ + const struct regmap_config *regmap_cfg; + struct regmap *regmap; + int variant; + + variant = rk8xx_i2c_get_variant(client); + if (variant < 0) + return variant; + + switch (variant) { + case RK805_ID: + regmap_cfg = &rk805_regmap_config; + break; + case RK808_ID: + regmap_cfg = &rk808_regmap_config; + break; + case RK818_ID: + regmap_cfg = &rk818_regmap_config; + break; + case RK809_ID: + case RK817_ID: + regmap_cfg = &rk817_regmap_config; + break; + default: + return dev_err_probe(&client->dev, -EINVAL, "Unsupported RK8XX ID %x\n", variant); + } + + regmap = devm_regmap_init_i2c(client, regmap_cfg); + if (IS_ERR(regmap)) + return dev_err_probe(&client->dev, PTR_ERR(regmap), + "regmap initialization failed\n"); + + return rk8xx_probe(&client->dev, variant, client->irq, regmap); +} + +static void rk8xx_i2c_shutdown(struct i2c_client *client) +{ + rk8xx_shutdown(&client->dev); +} + +static SIMPLE_DEV_PM_OPS(rk8xx_i2c_pm_ops, rk8xx_suspend, rk8xx_resume); + +static const struct of_device_id rk8xx_i2c_of_match[] = { + { .compatible = "rockchip,rk805" }, + { .compatible = "rockchip,rk808" }, + { .compatible = "rockchip,rk809" }, + { .compatible = "rockchip,rk817" }, + { .compatible = "rockchip,rk818" }, + { }, +}; +MODULE_DEVICE_TABLE(of, rk8xx_i2c_of_match); + +static struct i2c_driver rk8xx_i2c_driver = { + .driver = { + .name = "rk8xx-i2c", + .of_match_table = rk8xx_i2c_of_match, + .pm = &rk8xx_i2c_pm_ops, + }, + .probe_new = rk8xx_i2c_probe, + .shutdown = rk8xx_i2c_shutdown, +}; +module_i2c_driver(rk8xx_i2c_driver); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Chris Zhong "); +MODULE_AUTHOR("Zhang Qing "); +MODULE_AUTHOR("Wadim Egorov "); +MODULE_DESCRIPTION("RK8xx I2C PMIC driver"); diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig index dcb53c4a9584..38e6c5401554 100644 --- a/drivers/pinctrl/Kconfig +++ b/drivers/pinctrl/Kconfig @@ -407,7 +407,7 @@ config PINCTRL_PISTACHIO config PINCTRL_RK805 tristate "Pinctrl and GPIO driver for RK805 PMIC" - depends on MFD_RK808 + depends on MFD_RK8XX select GPIOLIB select PINMUX select GENERIC_PINCONF diff --git a/drivers/power/supply/Kconfig b/drivers/power/supply/Kconfig index c78be9f322e6..4a5e8e1d1237 100644 --- a/drivers/power/supply/Kconfig +++ b/drivers/power/supply/Kconfig @@ -706,7 +706,7 @@ config CHARGER_BQ256XX config CHARGER_RK817 tristate "Rockchip RK817 PMIC Battery Charger" - depends on MFD_RK808 + depends on MFD_RK8XX help Say Y to include support for Rockchip RK817 Battery Charger. diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig index aae28d0a489c..7f479753de5c 100644 --- a/drivers/regulator/Kconfig +++ b/drivers/regulator/Kconfig @@ -1056,7 +1056,7 @@ config REGULATOR_RC5T583 config REGULATOR_RK808 tristate "Rockchip RK805/RK808/RK809/RK817/RK818 Power regulators" - depends on MFD_RK808 + depends on MFD_RK8XX help Select this option to enable the power regulator of ROCKCHIP PMIC RK805,RK809&RK817,RK808 and RK818. diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index 5a71579af0a1..86c5cee2cb33 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig @@ -395,7 +395,7 @@ config RTC_DRV_NCT3018Y config RTC_DRV_RK808 tristate "Rockchip RK805/RK808/RK809/RK817/RK818 RTC" - depends on MFD_RK808 + depends on MFD_RK8XX help If you say yes here you will get support for the RTC of RK805, RK809 and RK817, RK808 and RK818 PMIC. diff --git a/include/linux/mfd/rk808.h b/include/linux/mfd/rk808.h index a89ddd9ba68e..4183427a80fe 100644 --- a/include/linux/mfd/rk808.h +++ b/include/linux/mfd/rk808.h @@ -794,4 +794,10 @@ struct rk808 { const struct regmap_config *regmap_cfg; const struct regmap_irq_chip *regmap_irq_chip; }; + +void rk8xx_shutdown(struct device *dev); +int rk8xx_probe(struct device *dev, int variant, unsigned int irq, struct regmap *regmap); +int rk8xx_suspend(struct device *dev); +int rk8xx_resume(struct device *dev); + #endif /* __LINUX_REGULATOR_RK808_H */ diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 07747565c3b5..8b7cc25a6618 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -1257,7 +1257,7 @@ config SND_SOC_RK3328 config SND_SOC_RK817 tristate "Rockchip RK817 audio CODEC" - depends on MFD_RK808 || COMPILE_TEST + depends on MFD_RK8XX || COMPILE_TEST config SND_SOC_RL6231 tristate From patchwork Tue Mar 7 15:36:13 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sebastian Reichel X-Patchwork-Id: 660053 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id D0E94C6FD20 for ; Tue, 7 Mar 2023 15:36:48 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230244AbjCGPgr (ORCPT ); Tue, 7 Mar 2023 10:36:47 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:38194 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231312AbjCGPgk (ORCPT ); Tue, 7 Mar 2023 10:36:40 -0500 Received: from madras.collabora.co.uk (madras.collabora.co.uk [46.235.227.172]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id EE751BDF7; Tue, 7 Mar 2023 07:36:34 -0800 (PST) Received: from jupiter.universe (dyndsl-091-248-189-073.ewe-ip-backbone.de [91.248.189.73]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits)) (No client certificate requested) (Authenticated sender: sre) by madras.collabora.co.uk (Postfix) with ESMTPSA id AFFEA6602FEE; Tue, 7 Mar 2023 15:36:23 +0000 (GMT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=collabora.com; s=mail; t=1678203383; bh=fdyAe7nIfN3rrCxcXk+9N+Frkojy72QgCF7OgKcRKuM=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=fSvZNvbvHOQZcWYR4KEMGXLptddZlffk6ocxKnI9pvAduVuAf4L1iaB8k5dUw2SfK KWJS/Wf0hFh7Yl9AnCetBbA+ye/z5WZZfV1NLGAFlpVHtpMkCY3v74O58t57PI83b9 mWtYBLSK3KT9jl3jqlBbz7YgEHcosQLPsExopy2CRSyMcsyBgHzQRAeI1OQ8XBvqJ2 TXaETrBe7MpWJffA3EZHkoz+0jjO8WULMI1FDqXZQicVjyvJFLHusLm3XpWRB+ydzX OIsA8G2PQUg/g6oocbFNR9EgzL4EIX6KLMs5Bm0rq2spzGhuzM/zqQCNBjTsrwlEw+ NpxmafYHMNLcQ== Received: by jupiter.universe (Postfix, from userid 1000) id 2ED3E48011F; Tue, 7 Mar 2023 16:36:19 +0100 (CET) From: Sebastian Reichel To: Heiko Stuebner , Rob Herring , Krzysztof Kozlowski , Lee Jones Cc: Michael Turquette , Stephen Boyd , Linus Walleij , Mark Brown , Liam Girdwood , Alexandre Belloni , Alessandro Zummo , linux-rockchip@lists.infradead.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, Sebastian Reichel , kernel@collabora.com, Rob Herring Subject: [PATCHv7 07/11] dt-bindings: mfd: add rk806 binding Date: Tue, 7 Mar 2023 16:36:13 +0100 Message-Id: <20230307153617.643260-8-sebastian.reichel@collabora.com> X-Mailer: git-send-email 2.39.2 In-Reply-To: <20230307153617.643260-1-sebastian.reichel@collabora.com> References: <20230307153617.643260-1-sebastian.reichel@collabora.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: devicetree@vger.kernel.org Add DT binding document for Rockchip's RK806 PMIC. Reviewed-by: Rob Herring Signed-off-by: Sebastian Reichel --- .../bindings/mfd/rockchip,rk806.yaml | 406 ++++++++++++++++++ 1 file changed, 406 insertions(+) create mode 100644 Documentation/devicetree/bindings/mfd/rockchip,rk806.yaml diff --git a/Documentation/devicetree/bindings/mfd/rockchip,rk806.yaml b/Documentation/devicetree/bindings/mfd/rockchip,rk806.yaml new file mode 100644 index 000000000000..cf2500f2e9a0 --- /dev/null +++ b/Documentation/devicetree/bindings/mfd/rockchip,rk806.yaml @@ -0,0 +1,406 @@ +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/mfd/rockchip,rk806.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: RK806 Power Management Integrated Circuit + +maintainers: + - Sebastian Reichel + +description: + Rockchip RK806 series PMIC. This device consists of an spi or + i2c controlled MFD that includes multiple switchable regulators. + +properties: + compatible: + enum: + - rockchip,rk806 + + reg: + maxItems: 1 + + interrupts: + maxItems: 1 + + gpio-controller: true + + '#gpio-cells': + const: 2 + + vcc1-supply: + description: + The input supply for dcdc-reg1. + + vcc2-supply: + description: + The input supply for dcdc-reg2. + + vcc3-supply: + description: + The input supply for dcdc-reg3. + + vcc4-supply: + description: + The input supply for dcdc-reg4. + + vcc5-supply: + description: + The input supply for dcdc-reg5. + + vcc6-supply: + description: + The input supply for dcdc-reg6. + + vcc7-supply: + description: + The input supply for dcdc-reg7. + + vcc8-supply: + description: + The input supply for dcdc-reg8. + + vcc9-supply: + description: + The input supply for dcdc-reg9. + + vcc10-supply: + description: + The input supply for dcdc-reg10. + + vcc11-supply: + description: + The input supply for pldo-reg1, pldo-reg2 and pldo-reg3. + + vcc12-supply: + description: + The input supply for pldo-reg4 and pldo-reg5. + + vcc13-supply: + description: + The input supply for nldo-reg1, nldo-reg2 and nldo-reg3. + + vcc14-supply: + description: + The input supply for nldo-reg4 and nldo-reg5. + + vcca-supply: + description: + The input supply for pldo-reg6. + + regulators: + type: object + additionalProperties: false + patternProperties: + "^(dcdc-reg([1-9]|10)|pldo-reg[1-6]|nldo-reg[1-5])$": + type: object + $ref: /schemas/regulator/regulator.yaml# + unevaluatedProperties: false + +patternProperties: + '-pins$': + type: object + additionalProperties: false + $ref: /schemas/pinctrl/pinmux-node.yaml + + properties: + function: + enum: [pin_fun0, pin_fun1, pin_fun2, pin_fun3, pin_fun4, pin_fun5] + + pins: + $ref: /schemas/types.yaml#/definitions/string + enum: [gpio_pwrctrl1, gpio_pwrctrl2, gpio_pwrctrl3] + +allOf: + - $ref: /schemas/spi/spi-peripheral-props.yaml + +required: + - compatible + - reg + - interrupts + +unevaluatedProperties: false + +examples: + - | + #include + #include + #include + spi { + #address-cells = <1>; + #size-cells = <0>; + + pmic@0 { + compatible = "rockchip,rk806"; + reg = <0x0>; + + interrupts = <7 IRQ_TYPE_LEVEL_LOW>; + + vcc1-supply = <&vcc5v0_sys>; + vcc2-supply = <&vcc5v0_sys>; + vcc3-supply = <&vcc5v0_sys>; + vcc4-supply = <&vcc5v0_sys>; + vcc5-supply = <&vcc5v0_sys>; + vcc6-supply = <&vcc5v0_sys>; + vcc7-supply = <&vcc5v0_sys>; + vcc8-supply = <&vcc5v0_sys>; + vcc9-supply = <&vcc5v0_sys>; + vcc10-supply = <&vcc5v0_sys>; + vcc11-supply = <&vcc_2v0_pldo_s3>; + vcc12-supply = <&vcc5v0_sys>; + vcc13-supply = <&vcc5v0_sys>; + vcc14-supply = <&vcc_1v1_nldo_s3>; + vcca-supply = <&vcc5v0_sys>; + + regulators { + vdd_gpu_s0: dcdc-reg1 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <550000>; + regulator-max-microvolt = <950000>; + regulator-ramp-delay = <12500>; + regulator-name = "vdd_gpu_s0"; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vdd_npu_s0: dcdc-reg2 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <550000>; + regulator-max-microvolt = <950000>; + regulator-ramp-delay = <12500>; + regulator-name = "vdd_npu_s0"; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vdd_log_s0: dcdc-reg3 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <750000>; + regulator-max-microvolt = <750000>; + regulator-ramp-delay = <12500>; + regulator-name = "vdd_log_s0"; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <750000>; + }; + }; + + vdd_vdenc_s0: dcdc-reg4 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <550000>; + regulator-max-microvolt = <950000>; + regulator-ramp-delay = <12500>; + regulator-name = "vdd_vdenc_s0"; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vdd_gpu_mem_s0: dcdc-reg5 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <675000>; + regulator-max-microvolt = <950000>; + regulator-ramp-delay = <12500>; + regulator-name = "vdd_gpu_mem_s0"; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vdd_npu_mem_s0: dcdc-reg6 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <675000>; + regulator-max-microvolt = <950000>; + regulator-ramp-delay = <12500>; + regulator-name = "vdd_npu_mem_s0"; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vcc_2v0_pldo_s3: dcdc-reg7 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <2000000>; + regulator-max-microvolt = <2000000>; + regulator-ramp-delay = <12500>; + regulator-name = "vdd_2v0_pldo_s3"; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <2000000>; + }; + }; + + vdd_vdenc_mem_s0: dcdc-reg8 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <675000>; + regulator-max-microvolt = <950000>; + regulator-ramp-delay = <12500>; + regulator-name = "vdd_vdenc_mem_s0"; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vdd2_ddr_s3: dcdc-reg9 { + regulator-always-on; + regulator-boot-on; + regulator-name = "vdd2_ddr_s3"; + regulator-state-mem { + regulator-on-in-suspend; + }; + }; + + vcc_1v1_nldo_s3: dcdc-reg10 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1100000>; + regulator-max-microvolt = <1100000>; + regulator-ramp-delay = <12500>; + regulator-name = "vcc_1v1_nldo_s3"; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1100000>; + }; + }; + + avcc_1v8_s0: pldo-reg1 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-ramp-delay = <12500>; + regulator-name = "avcc_1v8_s0"; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vdd1_1v8_ddr_s3: pldo-reg2 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-ramp-delay = <12500>; + regulator-name = "vdd1_1v8_ddr_s3"; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1800000>; + }; + }; + + vcc_1v8_s3: pldo-reg3 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-ramp-delay = <12500>; + regulator-name = "vcc_1v8_s3"; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1800000>; + }; + }; + + vcc_3v3_s0: pldo-reg4 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-ramp-delay = <12500>; + regulator-name = "vcc_3v3_s0"; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vccio_sd_s0: pldo-reg5 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <3300000>; + regulator-ramp-delay = <12500>; + regulator-name = "vccio_sd_s0"; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + master_pldo6_s3: pldo-reg6 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-name = "master_pldo6_s3"; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1800000>; + }; + }; + + vdd_0v75_s3: nldo-reg1 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <750000>; + regulator-max-microvolt = <750000>; + regulator-ramp-delay = <12500>; + regulator-name = "vdd_0v75_s3"; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <750000>; + }; + }; + + vdd2l_0v9_ddr_s3: nldo-reg2 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <900000>; + regulator-max-microvolt = <900000>; + regulator-name = "vdd2l_0v9_ddr_s3"; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <900000>; + }; + }; + + master_nldo3: nldo-reg3 { + regulator-name = "master_nldo3"; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + avdd_0v75_s0: nldo-reg4 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <750000>; + regulator-max-microvolt = <750000>; + regulator-name = "avdd_0v75_s0"; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + + vdd_0v85_s0: nldo-reg5 { + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <850000>; + regulator-max-microvolt = <850000>; + regulator-name = "vdd_0v85_s0"; + regulator-state-mem { + regulator-off-in-suspend; + }; + }; + }; + }; + }; From patchwork Tue Mar 7 15:36:16 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sebastian Reichel X-Patchwork-Id: 660050 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 335D2C678D4 for ; Tue, 7 Mar 2023 15:37:02 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231422AbjCGPhA (ORCPT ); Tue, 7 Mar 2023 10:37:00 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:38436 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231313AbjCGPgs (ORCPT ); Tue, 7 Mar 2023 10:36:48 -0500 Received: from madras.collabora.co.uk (madras.collabora.co.uk [IPv6:2a00:1098:0:82:1000:25:2eeb:e5ab]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 4E6423CE3C; Tue, 7 Mar 2023 07:36:36 -0800 (PST) Received: from jupiter.universe (dyndsl-091-248-189-073.ewe-ip-backbone.de [91.248.189.73]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits)) (No client certificate requested) (Authenticated sender: sre) by madras.collabora.co.uk (Postfix) with ESMTPSA id CA4FB6602FF1; Tue, 7 Mar 2023 15:36:23 +0000 (GMT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=collabora.com; s=mail; t=1678203384; bh=ZQ/T8MJuQX09A1tGzbRQ4ENDhRkPn5npxjDPMRKuSs0=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=AEm1loiXWRFVuRH0aivajzoBX3Lnloq+AtnWWcUPKDI1vsPB9wUlJMXaw9Aay+TgA 9yHBdfcPViLA9n5qtixSmxTp/8GhWNNnqNvHC3pnNorxZorWNPdet+M6D3iEfBc9iu ACtyMBrJyb/HrmshhNJ+Pm9rsIXNfyAZePAIEUEKws2yqmCLcWCqz7nkcUbuUVTStX Xrh0FXDebflhk9S1wvC73NJAcLZdyngbTiJXa6n8f7o0CYdI+NYEozU0k9lyoYupzL 8So9mNrG1A3DEd//lOLlUktUS5qANycx6M12trpq0sbf9KNq0q4R4TDQqzRLGowHtg dw6fTi+P4v5qQ== Received: by jupiter.universe (Postfix, from userid 1000) id 36E64480122; Tue, 7 Mar 2023 16:36:19 +0100 (CET) From: Sebastian Reichel To: Heiko Stuebner , Rob Herring , Krzysztof Kozlowski , Lee Jones Cc: Michael Turquette , Stephen Boyd , Linus Walleij , Mark Brown , Liam Girdwood , Alexandre Belloni , Alessandro Zummo , linux-rockchip@lists.infradead.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, Sebastian Reichel , kernel@collabora.com Subject: [PATCHv7 10/11] regulator: expose regulator_find_closest_bigger Date: Tue, 7 Mar 2023 16:36:16 +0100 Message-Id: <20230307153617.643260-11-sebastian.reichel@collabora.com> X-Mailer: git-send-email 2.39.2 In-Reply-To: <20230307153617.643260-1-sebastian.reichel@collabora.com> References: <20230307153617.643260-1-sebastian.reichel@collabora.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: devicetree@vger.kernel.org Expose and document the table lookup logic used by regulator_set_ramp_delay_regmap, so that it can be reused for devices that cannot be configured via regulator_set_ramp_delay_regmap. Signed-off-by: Sebastian Reichel --- drivers/regulator/helpers.c | 22 ++++++++++++++++++---- include/linux/regulator/driver.h | 2 ++ 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/drivers/regulator/helpers.c b/drivers/regulator/helpers.c index ad2237a95572..586f42e378ee 100644 --- a/drivers/regulator/helpers.c +++ b/drivers/regulator/helpers.c @@ -902,8 +902,21 @@ bool regulator_is_equal(struct regulator *reg1, struct regulator *reg2) } EXPORT_SYMBOL_GPL(regulator_is_equal); -static int find_closest_bigger(unsigned int target, const unsigned int *table, - unsigned int num_sel, unsigned int *sel) +/** + * regulator_find_closest_bigger - helper to find offset in ramp delay table + * + * @target: targeted ramp_delay + * @table: table with supported ramp delays + * @num_sel: number of entries in the table + * @sel: Pointer to store table offset + * + * This is the internal helper used by regulator_set_ramp_delay_regmap to + * map ramp delay to register value. It should only be used directly if + * regulator_set_ramp_delay_regmap cannot handle a specific device setup + * (e.g. because the value is split over multiple registers). + */ +int regulator_find_closest_bigger(unsigned int target, const unsigned int *table, + unsigned int num_sel, unsigned int *sel) { unsigned int s, tmp, max, maxsel = 0; bool found = false; @@ -933,6 +946,7 @@ static int find_closest_bigger(unsigned int target, const unsigned int *table, return 0; } +EXPORT_SYMBOL_GPL(regulator_find_closest_bigger); /** * regulator_set_ramp_delay_regmap - set_ramp_delay() helper @@ -951,8 +965,8 @@ int regulator_set_ramp_delay_regmap(struct regulator_dev *rdev, int ramp_delay) if (WARN_ON(!rdev->desc->n_ramp_values || !rdev->desc->ramp_delay_table)) return -EINVAL; - ret = find_closest_bigger(ramp_delay, rdev->desc->ramp_delay_table, - rdev->desc->n_ramp_values, &sel); + ret = regulator_find_closest_bigger(ramp_delay, rdev->desc->ramp_delay_table, + rdev->desc->n_ramp_values, &sel); if (ret) { dev_warn(rdev_get_dev(rdev), diff --git a/include/linux/regulator/driver.h b/include/linux/regulator/driver.h index d3b4a3d4514a..c6ef7d68eb9a 100644 --- a/include/linux/regulator/driver.h +++ b/include/linux/regulator/driver.h @@ -758,6 +758,8 @@ int regulator_set_current_limit_regmap(struct regulator_dev *rdev, int min_uA, int max_uA); int regulator_get_current_limit_regmap(struct regulator_dev *rdev); void *regulator_get_init_drvdata(struct regulator_init_data *reg_init_data); +int regulator_find_closest_bigger(unsigned int target, const unsigned int *table, + unsigned int num_sel, unsigned int *sel); int regulator_set_ramp_delay_regmap(struct regulator_dev *rdev, int ramp_delay); int regulator_sync_voltage_rdev(struct regulator_dev *rdev); From patchwork Tue Mar 7 15:36:17 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sebastian Reichel X-Patchwork-Id: 660051 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 2B44FC74A44 for ; Tue, 7 Mar 2023 15:36:57 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231352AbjCGPg4 (ORCPT ); Tue, 7 Mar 2023 10:36:56 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:38194 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229849AbjCGPgq (ORCPT ); Tue, 7 Mar 2023 10:36:46 -0500 Received: from madras.collabora.co.uk (madras.collabora.co.uk [46.235.227.172]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 558981BADC; Tue, 7 Mar 2023 07:36:35 -0800 (PST) Received: from jupiter.universe (dyndsl-091-248-189-073.ewe-ip-backbone.de [91.248.189.73]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits)) (No client certificate requested) (Authenticated sender: sre) by madras.collabora.co.uk (Postfix) with ESMTPSA id D0E346602FF2; Tue, 7 Mar 2023 15:36:23 +0000 (GMT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=collabora.com; s=mail; t=1678203384; bh=7gC0NSY34iAZF6bfxbC5gdEmQ+Af/fTPAVJFg33GcTw=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=S6X74IlgADJRhpNQXhPhuJRmz157aql65/spWQ8eckpMHjfx58rJJT6fOce/n8hgD OmebYmB3Pq01H6PFsaTeChhrZ83rRQm2GvezkAEj9IhnxYj1R/a1sDjeZ3PkSx5WdQ OLDPW2N4r5q4e/RtkguXSzt1kqOPAJC8G4zrEavMwVtBM7meY4xWwYSzjLVuMAEOJS fhd3cKowJUK4MtpJ+zwarlXNSfjFfyzXviZuk/3ndDYXddvcqZO/XTK0R7f+3GSlRW 8RGkRFa6rhaUw26MERRjZvy11w6YQXrfFINcvg8gScpVSc6SCT2txukX4R4kIXaAcJ hmbGPW618/iZg== Received: by jupiter.universe (Postfix, from userid 1000) id 39CFC480126; Tue, 7 Mar 2023 16:36:19 +0100 (CET) From: Sebastian Reichel To: Heiko Stuebner , Rob Herring , Krzysztof Kozlowski , Lee Jones Cc: Michael Turquette , Stephen Boyd , Linus Walleij , Mark Brown , Liam Girdwood , Alexandre Belloni , Alessandro Zummo , linux-rockchip@lists.infradead.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, Sebastian Reichel , kernel@collabora.com, shengfei Xu , Matti Vaittinen Subject: [PATCHv7 11/11] regulator: rk808: add rk806 support Date: Tue, 7 Mar 2023 16:36:17 +0100 Message-Id: <20230307153617.643260-12-sebastian.reichel@collabora.com> X-Mailer: git-send-email 2.39.2 In-Reply-To: <20230307153617.643260-1-sebastian.reichel@collabora.com> References: <20230307153617.643260-1-sebastian.reichel@collabora.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: devicetree@vger.kernel.org Add rk806 support to the existing rk808 regulator driver. This has been implemented using shengfei Xu's rk806 specific driver from the vendor tree as reference. Co-Developed-by: shengfei Xu Signed-off-by: shengfei Xu Reviewed-by: Matti Vaittinen Signed-off-by: Sebastian Reichel --- drivers/regulator/rk808-regulator.c | 383 ++++++++++++++++++++++++++++ 1 file changed, 383 insertions(+) diff --git a/drivers/regulator/rk808-regulator.c b/drivers/regulator/rk808-regulator.c index fa9fc1aa1ae3..3d534d411104 100644 --- a/drivers/regulator/rk808-regulator.c +++ b/drivers/regulator/rk808-regulator.c @@ -3,9 +3,11 @@ * Regulator driver for Rockchip RK805/RK808/RK818 * * Copyright (c) 2014, Fuzhou Rockchip Electronics Co., Ltd + * Copyright (c) 2021 Rockchip Electronics Co., Ltd. * * Author: Chris Zhong * Author: Zhang Qing + * Author: Xu Shengfei * * Copyright (C) 2016 PHYTEC Messtechnik GmbH * @@ -39,6 +41,13 @@ #define RK818_LDO3_ON_VSEL_MASK 0xf #define RK818_BOOST_ON_VSEL_MASK 0xe0 +#define RK806_DCDC_SLP_REG_OFFSET 0x0A +#define RK806_NLDO_SLP_REG_OFFSET 0x05 +#define RK806_PLDO_SLP_REG_OFFSET 0x06 + +#define RK806_BUCK_SEL_CNT 0xff +#define RK806_LDO_SEL_CNT 0xff + /* Ramp rate definitions for buck1 / buck2 only */ #define RK808_RAMP_RATE_OFFSET 3 #define RK808_RAMP_RATE_MASK (3 << RK808_RAMP_RATE_OFFSET) @@ -117,6 +126,34 @@ RK8XX_DESC_COM(_id, _match, _supply, _min, _max, _step, _vreg, \ _vmask, _ereg, _emask, 0, 0, _etime, &rk805_reg_ops) +#define RK806_REGULATOR(_name, _supply_name, _id, _ops,\ + _n_voltages, _vr, _er, _lr, ctrl_bit,\ + _rr, _rm, _rt)\ +[_id] = {\ + .name = _name,\ + .supply_name = _supply_name,\ + .of_match = of_match_ptr(_name),\ + .regulators_node = of_match_ptr("regulators"),\ + .id = _id,\ + .ops = &_ops,\ + .type = REGULATOR_VOLTAGE,\ + .n_voltages = _n_voltages,\ + .linear_ranges = _lr,\ + .n_linear_ranges = ARRAY_SIZE(_lr),\ + .vsel_reg = _vr,\ + .vsel_mask = 0xff,\ + .enable_reg = _er,\ + .enable_mask = ENABLE_MASK(ctrl_bit),\ + .enable_val = ENABLE_MASK(ctrl_bit),\ + .disable_val = DISABLE_VAL(ctrl_bit),\ + .of_map_mode = rk8xx_regulator_of_map_mode,\ + .ramp_reg = _rr,\ + .ramp_mask = _rm,\ + .ramp_delay_table = _rt, \ + .n_ramp_values = ARRAY_SIZE(_rt), \ + .owner = THIS_MODULE,\ + } + #define RK8XX_DESC(_id, _match, _supply, _min, _max, _step, _vreg, \ _vmask, _ereg, _emask, _etime) \ RK8XX_DESC_COM(_id, _match, _supply, _min, _max, _step, _vreg, \ @@ -153,6 +190,17 @@ RKXX_DESC_SWITCH_COM(_id, _match, _supply, _ereg, _emask, \ 0, 0, &rk808_switch_ops) +struct rk8xx_register_bit { + u8 reg; + u8 bit; +}; + +#define RK8XX_REG_BIT(_reg, _bit) \ + { \ + .reg = _reg, \ + .bit = BIT(_bit), \ + } + struct rk808_regulator_data { struct gpio_desc *dvs_gpio[2]; }; @@ -216,6 +264,133 @@ static const unsigned int rk817_buck1_4_ramp_table[] = { 3000, 6300, 12500, 25000 }; +static int rk806_set_mode_dcdc(struct regulator_dev *rdev, unsigned int mode) +{ + int rid = rdev_get_id(rdev); + int ctr_bit, reg; + + reg = RK806_POWER_FPWM_EN0 + rid / 8; + ctr_bit = rid % 8; + + switch (mode) { + case REGULATOR_MODE_FAST: + return regmap_update_bits(rdev->regmap, reg, + PWM_MODE_MSK << ctr_bit, + FPWM_MODE << ctr_bit); + case REGULATOR_MODE_NORMAL: + return regmap_update_bits(rdev->regmap, reg, + PWM_MODE_MSK << ctr_bit, + AUTO_PWM_MODE << ctr_bit); + default: + dev_err(rdev_get_dev(rdev), "mode unsupported: %u\n", mode); + return -EINVAL; + } + + return 0; +} + +static unsigned int rk806_get_mode_dcdc(struct regulator_dev *rdev) +{ + int rid = rdev_get_id(rdev); + int ctr_bit, reg; + unsigned int val; + int err; + + reg = RK806_POWER_FPWM_EN0 + rid / 8; + ctr_bit = rid % 8; + + err = regmap_read(rdev->regmap, reg, &val); + if (err) + return err; + + if ((val >> ctr_bit) & FPWM_MODE) + return REGULATOR_MODE_FAST; + else + return REGULATOR_MODE_NORMAL; +} + +static const struct rk8xx_register_bit rk806_dcdc_rate2[] = { + RK8XX_REG_BIT(0xEB, 0), + RK8XX_REG_BIT(0xEB, 1), + RK8XX_REG_BIT(0xEB, 2), + RK8XX_REG_BIT(0xEB, 3), + RK8XX_REG_BIT(0xEB, 4), + RK8XX_REG_BIT(0xEB, 5), + RK8XX_REG_BIT(0xEB, 6), + RK8XX_REG_BIT(0xEB, 7), + RK8XX_REG_BIT(0xEA, 0), + RK8XX_REG_BIT(0xEA, 1), +}; + +static const unsigned int rk806_ramp_delay_table_dcdc[] = { + 50000, 25000, 12500, 6250, 3125, 1560, 961, 390 +}; + +static int rk806_set_ramp_delay_dcdc(struct regulator_dev *rdev, int ramp_delay) +{ + int rid = rdev_get_id(rdev); + int regval, ramp_value, ret; + + ret = regulator_find_closest_bigger(ramp_delay, rdev->desc->ramp_delay_table, + rdev->desc->n_ramp_values, &ramp_value); + if (ret) { + dev_warn(rdev_get_dev(rdev), + "Can't set ramp-delay %u, setting %u\n", ramp_delay, + rdev->desc->ramp_delay_table[ramp_value]); + } + + regval = ramp_value << (ffs(rdev->desc->ramp_mask) - 1); + + ret = regmap_update_bits(rdev->regmap, rdev->desc->ramp_reg, + rdev->desc->ramp_mask, regval); + if (ret) + return ret; + + /* + * The above is effectively a copy of regulator_set_ramp_delay_regmap(), + * but that only stores the lower 2 bits for rk806 DCDC ramp. The MSB must + * be stored in a separate register, so this open codes the implementation + * to have access to the ramp_value. + */ + + regval = (ramp_value >> 2) & 0x1 ? rk806_dcdc_rate2[rid].bit : 0; + return regmap_update_bits(rdev->regmap, rk806_dcdc_rate2[rid].reg, + rk806_dcdc_rate2[rid].bit, + regval); +} + +static const unsigned int rk806_ramp_delay_table_ldo[] = { + 100000, 50000, 25000, 12500, 6280, 3120, 1900, 780 +}; + +static int rk806_set_suspend_voltage_range(struct regulator_dev *rdev, int reg_offset, int uv) +{ + int sel = regulator_map_voltage_linear_range(rdev, uv, uv); + unsigned int reg; + + if (sel < 0) + return -EINVAL; + + reg = rdev->desc->vsel_reg + reg_offset; + + return regmap_update_bits(rdev->regmap, reg, rdev->desc->vsel_mask, sel); +} + +static int rk806_set_suspend_voltage_range_dcdc(struct regulator_dev *rdev, int uv) +{ + return rk806_set_suspend_voltage_range(rdev, RK806_DCDC_SLP_REG_OFFSET, uv); +} + +static int rk806_set_suspend_voltage_range_nldo(struct regulator_dev *rdev, int uv) +{ + return rk806_set_suspend_voltage_range(rdev, RK806_NLDO_SLP_REG_OFFSET, uv); +} + +static int rk806_set_suspend_voltage_range_pldo(struct regulator_dev *rdev, int uv) +{ + return rk806_set_suspend_voltage_range(rdev, RK806_PLDO_SLP_REG_OFFSET, uv); +} + static int rk808_buck1_2_get_voltage_sel_regmap(struct regulator_dev *rdev) { struct rk808_regulator_data *pdata = rdev_get_drvdata(rdev); @@ -393,6 +568,45 @@ static int rk805_set_suspend_disable(struct regulator_dev *rdev) 0); } +static const struct rk8xx_register_bit rk806_suspend_bits[] = { + RK8XX_REG_BIT(RK806_POWER_SLP_EN0, 0), + RK8XX_REG_BIT(RK806_POWER_SLP_EN0, 1), + RK8XX_REG_BIT(RK806_POWER_SLP_EN0, 2), + RK8XX_REG_BIT(RK806_POWER_SLP_EN0, 3), + RK8XX_REG_BIT(RK806_POWER_SLP_EN0, 4), + RK8XX_REG_BIT(RK806_POWER_SLP_EN0, 5), + RK8XX_REG_BIT(RK806_POWER_SLP_EN0, 6), + RK8XX_REG_BIT(RK806_POWER_SLP_EN0, 7), + RK8XX_REG_BIT(RK806_POWER_SLP_EN1, 6), + RK8XX_REG_BIT(RK806_POWER_SLP_EN1, 7), + RK8XX_REG_BIT(RK806_POWER_SLP_EN1, 0), + RK8XX_REG_BIT(RK806_POWER_SLP_EN1, 1), + RK8XX_REG_BIT(RK806_POWER_SLP_EN1, 2), + RK8XX_REG_BIT(RK806_POWER_SLP_EN1, 3), + RK8XX_REG_BIT(RK806_POWER_SLP_EN1, 4), + RK8XX_REG_BIT(RK806_POWER_SLP_EN2, 1), + RK8XX_REG_BIT(RK806_POWER_SLP_EN2, 2), + RK8XX_REG_BIT(RK806_POWER_SLP_EN2, 3), + RK8XX_REG_BIT(RK806_POWER_SLP_EN2, 4), + RK8XX_REG_BIT(RK806_POWER_SLP_EN2, 5), + RK8XX_REG_BIT(RK806_POWER_SLP_EN2, 0), +}; + +static int rk806_set_suspend_enable(struct regulator_dev *rdev) +{ + int rid = rdev_get_id(rdev); + return regmap_update_bits(rdev->regmap, rk806_suspend_bits[rid].reg, + rk806_suspend_bits[rid].bit, + rk806_suspend_bits[rid].bit); +} + +static int rk806_set_suspend_disable(struct regulator_dev *rdev) +{ + int rid = rdev_get_id(rdev); + return regmap_update_bits(rdev->regmap, rk806_suspend_bits[rid].reg, + rk806_suspend_bits[rid].bit, 0); +} + static int rk808_set_suspend_enable(struct regulator_dev *rdev) { unsigned int reg; @@ -561,6 +775,64 @@ static const struct regulator_ops rk805_switch_ops = { .set_suspend_disable = rk805_set_suspend_disable, }; +static const struct regulator_ops rk806_ops_dcdc = { + .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, + .set_mode = rk806_set_mode_dcdc, + .get_mode = rk806_get_mode_dcdc, + + .enable = regulator_enable_regmap, + .disable = regulator_disable_regmap, + .is_enabled = rk8xx_is_enabled_wmsk_regmap, + + .set_suspend_mode = rk806_set_mode_dcdc, + .set_ramp_delay = rk806_set_ramp_delay_dcdc, + + .set_suspend_voltage = rk806_set_suspend_voltage_range_dcdc, + .set_suspend_enable = rk806_set_suspend_enable, + .set_suspend_disable = rk806_set_suspend_disable, +}; + +static const struct regulator_ops rk806_ops_nldo = { + .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 = regulator_set_ramp_delay_regmap, + + .set_suspend_voltage = rk806_set_suspend_voltage_range_nldo, + .set_suspend_enable = rk806_set_suspend_enable, + .set_suspend_disable = rk806_set_suspend_disable, +}; + +static const struct regulator_ops rk806_ops_pldo = { + .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 = regulator_set_ramp_delay_regmap, + + .set_suspend_voltage = rk806_set_suspend_voltage_range_pldo, + .set_suspend_enable = rk806_set_suspend_enable, + .set_suspend_disable = rk806_set_suspend_disable, +}; + static const struct regulator_ops rk808_buck1_2_ops = { .list_voltage = regulator_list_voltage_linear, .map_voltage = regulator_map_voltage_linear, @@ -743,6 +1015,112 @@ static const struct regulator_desc rk805_reg[] = { BIT(2), 400), }; +static const struct linear_range rk806_buck_voltage_ranges[] = { + REGULATOR_LINEAR_RANGE(500000, 0, 160, 6250), /* 500mV ~ 1500mV */ + REGULATOR_LINEAR_RANGE(1500000, 161, 237, 25000), /* 1500mV ~ 3400mV */ + REGULATOR_LINEAR_RANGE(3400000, 238, 255, 0), +}; + +static const struct linear_range rk806_ldo_voltage_ranges[] = { + REGULATOR_LINEAR_RANGE(500000, 0, 232, 12500), /* 500mV ~ 3400mV */ + REGULATOR_LINEAR_RANGE(3400000, 233, 255, 0), /* 500mV ~ 3400mV */ +}; + +static const struct regulator_desc rk806_reg[] = { + RK806_REGULATOR("dcdc-reg1", "vcc1", RK806_ID_DCDC1, rk806_ops_dcdc, + RK806_BUCK_SEL_CNT, RK806_BUCK1_ON_VSEL, + RK806_POWER_EN0, rk806_buck_voltage_ranges, 0, + RK806_BUCK1_CONFIG, 0xc0, rk806_ramp_delay_table_dcdc), + RK806_REGULATOR("dcdc-reg2", "vcc2", RK806_ID_DCDC2, rk806_ops_dcdc, + RK806_BUCK_SEL_CNT, RK806_BUCK2_ON_VSEL, + RK806_POWER_EN0, rk806_buck_voltage_ranges, 1, + RK806_BUCK2_CONFIG, 0xc0, rk806_ramp_delay_table_dcdc), + RK806_REGULATOR("dcdc-reg3", "vcc3", RK806_ID_DCDC3, rk806_ops_dcdc, + RK806_BUCK_SEL_CNT, RK806_BUCK3_ON_VSEL, + RK806_POWER_EN0, rk806_buck_voltage_ranges, 2, + RK806_BUCK3_CONFIG, 0xc0, rk806_ramp_delay_table_dcdc), + RK806_REGULATOR("dcdc-reg4", "vcc4", RK806_ID_DCDC4, rk806_ops_dcdc, + RK806_BUCK_SEL_CNT, RK806_BUCK4_ON_VSEL, + RK806_POWER_EN0, rk806_buck_voltage_ranges, 3, + RK806_BUCK4_CONFIG, 0xc0, rk806_ramp_delay_table_dcdc), + + RK806_REGULATOR("dcdc-reg5", "vcc5", RK806_ID_DCDC5, rk806_ops_dcdc, + RK806_BUCK_SEL_CNT, RK806_BUCK5_ON_VSEL, + RK806_POWER_EN1, rk806_buck_voltage_ranges, 0, + RK806_BUCK5_CONFIG, 0xc0, rk806_ramp_delay_table_dcdc), + RK806_REGULATOR("dcdc-reg6", "vcc6", RK806_ID_DCDC6, rk806_ops_dcdc, + RK806_BUCK_SEL_CNT, RK806_BUCK6_ON_VSEL, + RK806_POWER_EN1, rk806_buck_voltage_ranges, 1, + RK806_BUCK6_CONFIG, 0xc0, rk806_ramp_delay_table_dcdc), + RK806_REGULATOR("dcdc-reg7", "vcc7", RK806_ID_DCDC7, rk806_ops_dcdc, + RK806_BUCK_SEL_CNT, RK806_BUCK7_ON_VSEL, + RK806_POWER_EN1, rk806_buck_voltage_ranges, 2, + RK806_BUCK7_CONFIG, 0xc0, rk806_ramp_delay_table_dcdc), + RK806_REGULATOR("dcdc-reg8", "vcc8", RK806_ID_DCDC8, rk806_ops_dcdc, + RK806_BUCK_SEL_CNT, RK806_BUCK8_ON_VSEL, + RK806_POWER_EN1, rk806_buck_voltage_ranges, 3, + RK806_BUCK8_CONFIG, 0xc0, rk806_ramp_delay_table_dcdc), + + RK806_REGULATOR("dcdc-reg9", "vcc9", RK806_ID_DCDC9, rk806_ops_dcdc, + RK806_BUCK_SEL_CNT, RK806_BUCK9_ON_VSEL, + RK806_POWER_EN2, rk806_buck_voltage_ranges, 0, + RK806_BUCK9_CONFIG, 0xc0, rk806_ramp_delay_table_dcdc), + RK806_REGULATOR("dcdc-reg10", "vcc10", RK806_ID_DCDC10, rk806_ops_dcdc, + RK806_BUCK_SEL_CNT, RK806_BUCK10_ON_VSEL, + RK806_POWER_EN2, rk806_buck_voltage_ranges, 1, + RK806_BUCK10_CONFIG, 0xc0, rk806_ramp_delay_table_dcdc), + + RK806_REGULATOR("nldo-reg1", "vcc13", RK806_ID_NLDO1, rk806_ops_nldo, + RK806_LDO_SEL_CNT, RK806_NLDO1_ON_VSEL, + RK806_POWER_EN3, rk806_ldo_voltage_ranges, 0, + 0xEA, 0x38, rk806_ramp_delay_table_ldo), + RK806_REGULATOR("nldo-reg2", "vcc13", RK806_ID_NLDO2, rk806_ops_nldo, + RK806_LDO_SEL_CNT, RK806_NLDO2_ON_VSEL, + RK806_POWER_EN3, rk806_ldo_voltage_ranges, 1, + 0xEA, 0x38, rk806_ramp_delay_table_ldo), + RK806_REGULATOR("nldo-reg3", "vcc13", RK806_ID_NLDO3, rk806_ops_nldo, + RK806_LDO_SEL_CNT, RK806_NLDO3_ON_VSEL, + RK806_POWER_EN3, rk806_ldo_voltage_ranges, 2, + 0xEA, 0x38, rk806_ramp_delay_table_ldo), + RK806_REGULATOR("nldo-reg4", "vcc14", RK806_ID_NLDO4, rk806_ops_nldo, + RK806_LDO_SEL_CNT, RK806_NLDO4_ON_VSEL, + RK806_POWER_EN3, rk806_ldo_voltage_ranges, 3, + 0xEA, 0x38, rk806_ramp_delay_table_ldo), + + RK806_REGULATOR("nldo-reg5", "vcc14", RK806_ID_NLDO5, rk806_ops_nldo, + RK806_LDO_SEL_CNT, RK806_NLDO5_ON_VSEL, + RK806_POWER_EN5, rk806_ldo_voltage_ranges, 2, + 0xEA, 0x38, rk806_ramp_delay_table_ldo), + + RK806_REGULATOR("pldo-reg1", "vcc11", RK806_ID_PLDO1, rk806_ops_pldo, + RK806_LDO_SEL_CNT, RK806_PLDO1_ON_VSEL, + RK806_POWER_EN4, rk806_ldo_voltage_ranges, 1, + 0xEA, 0x38, rk806_ramp_delay_table_ldo), + RK806_REGULATOR("pldo-reg2", "vcc11", RK806_ID_PLDO2, rk806_ops_pldo, + RK806_LDO_SEL_CNT, RK806_PLDO2_ON_VSEL, + RK806_POWER_EN4, rk806_ldo_voltage_ranges, 2, + 0xEA, 0x38, rk806_ramp_delay_table_ldo), + RK806_REGULATOR("pldo-reg3", "vcc11", RK806_ID_PLDO3, rk806_ops_pldo, + RK806_LDO_SEL_CNT, RK806_PLDO3_ON_VSEL, + RK806_POWER_EN4, rk806_ldo_voltage_ranges, 3, + 0xEA, 0x38, rk806_ramp_delay_table_ldo), + + RK806_REGULATOR("pldo-reg4", "vcc12", RK806_ID_PLDO4, rk806_ops_pldo, + RK806_LDO_SEL_CNT, RK806_PLDO4_ON_VSEL, + RK806_POWER_EN5, rk806_ldo_voltage_ranges, 0, + 0xEA, 0x38, rk806_ramp_delay_table_ldo), + RK806_REGULATOR("pldo-reg5", "vcc12", RK806_ID_PLDO5, rk806_ops_pldo, + RK806_LDO_SEL_CNT, RK806_PLDO5_ON_VSEL, + RK806_POWER_EN5, rk806_ldo_voltage_ranges, 1, + 0xEA, 0x38, rk806_ramp_delay_table_ldo), + + RK806_REGULATOR("pldo-reg6", "vcca", RK806_ID_PLDO6, rk806_ops_pldo, + RK806_LDO_SEL_CNT, RK806_PLDO6_ON_VSEL, + RK806_POWER_EN4, rk806_ldo_voltage_ranges, 0, + 0xEA, 0x38, rk806_ramp_delay_table_ldo), +}; + + static const struct regulator_desc rk808_reg[] = { { .name = "DCDC_REG1", @@ -1312,6 +1690,10 @@ static int rk808_regulator_probe(struct platform_device *pdev) regulators = rk805_reg; nregulators = RK805_NUM_REGULATORS; break; + case RK806_ID: + regulators = rk806_reg; + nregulators = ARRAY_SIZE(rk806_reg); + break; case RK808_ID: regulators = rk808_reg; nregulators = RK808_NUM_REGULATORS; @@ -1365,5 +1747,6 @@ MODULE_AUTHOR("Tony xie "); MODULE_AUTHOR("Chris Zhong "); MODULE_AUTHOR("Zhang Qing "); MODULE_AUTHOR("Wadim Egorov "); +MODULE_AUTHOR("Xu Shengfei "); MODULE_LICENSE("GPL"); MODULE_ALIAS("platform:rk808-regulator");