From patchwork Mon Apr 22 09:57:25 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Linus Walleij X-Patchwork-Id: 2471551 Return-Path: X-Original-To: patchwork-linux-arm@patchwork.kernel.org Delivered-To: patchwork-process-083081@patchwork1.kernel.org Received: from casper.infradead.org (casper.infradead.org [85.118.1.10]) by patchwork1.kernel.org (Postfix) with ESMTP id 686B13FD40 for ; Mon, 22 Apr 2013 11:34:16 +0000 (UTC) Received: from merlin.infradead.org ([2001:4978:20e::2]) by casper.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1UUDXL-0000HH-58; Mon, 22 Apr 2013 09:59:53 +0000 Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1UUDVR-00030e-Fj; Mon, 22 Apr 2013 09:57:53 +0000 Received: from eu1sys200aog103.obsmtp.com ([207.126.144.115]) by merlin.infradead.org with smtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1UUDVM-00030A-C4 for linux-arm-kernel@lists.infradead.org; Mon, 22 Apr 2013 09:57:51 +0000 Received: from beta.dmz-us.st.com ([167.4.1.35]) (using TLSv1) by eu1sys200aob103.postini.com ([207.126.147.11]) with SMTP ID DSNKUXUJkgKEWKzichV6pqZFn0Jg9MCLS5ja@postini.com; Mon, 22 Apr 2013 09:57:48 UTC Received: from zeta.dmz-us.st.com (ns4.st.com [167.4.16.71]) by beta.dmz-us.st.com (STMicroelectronics) with ESMTP id 04D5B62; Mon, 22 Apr 2013 09:56:36 +0000 (GMT) Received: from relay1.stm.gmessaging.net (unknown [10.230.100.17]) by zeta.dmz-us.st.com (STMicroelectronics) with ESMTP id 9D4AE3F; Mon, 22 Apr 2013 03:06:03 +0000 (GMT) Received: from exdcvycastm022.EQ1STM.local (alteon-source-exch [10.230.100.61]) (using TLSv1 with cipher RC4-MD5 (128/128 bits)) (Client CN "exdcvycastm022", Issuer "exdcvycastm022" (not verified)) by relay1.stm.gmessaging.net (Postfix) with ESMTPS id 4FECD24C07C; Mon, 22 Apr 2013 11:57:26 +0200 (CEST) Received: from steludxu4075.lud.stericsson.com (10.230.100.153) by smtp.stericsson.com (10.230.100.30) with Microsoft SMTP Server (TLS) id 8.3.279.5; Mon, 22 Apr 2013 11:57:31 +0200 From: Linus Walleij To: , Liam Girdwood , Mark Brown Subject: [PATCH 14/23] regulator: ab3100: device tree support Date: Mon, 22 Apr 2013 11:57:25 +0200 Message-ID: <1366624645-6614-1-git-send-email-linus.walleij@stericsson.com> X-Mailer: git-send-email 1.7.11.3 MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20130422_055750_127704_FCDAED00 X-CRM114-Status: GOOD ( 27.76 ) X-Spam-Score: -4.2 (----) X-Spam-Report: SpamAssassin version 3.3.2 on merlin.infradead.org summary: Content analysis details: (-4.2 points) pts rule name description ---- ---------------------- -------------------------------------------------- -2.3 RCVD_IN_DNSWL_MED RBL: Sender listed at http://www.dnswl.org/, medium trust [207.126.144.115 listed in list.dnswl.org] -1.9 BAYES_00 BODY: Bayes spam probability is 0 to 1% [score: 0.0000] Cc: devicetree-discuss@lists.ozlabs.org, Lee Jones , Linus Walleij , Arnd Bergmann X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org From: Linus Walleij This implements device tree support for the AB3100 regulators driver. The initial settings are moved out of platform data and into the driver for the device tree case, as it appears that there is no way to supply this as AUXDATA for an I2C device. The style and bindings are heavily inspired by Lee Jones' style for AB8500. Cc: Lee Jones Cc: Mark Brown Signed-off-by: Linus Walleij Acked-by: Lee Jones --- Hi Mark, seeking an ACK on this to take it through the ARM SoC tree. --- drivers/mfd/ab3100-core.c | 1 + drivers/regulator/ab3100.c | 123 ++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 118 insertions(+), 6 deletions(-) diff --git a/drivers/mfd/ab3100-core.c b/drivers/mfd/ab3100-core.c index 2ec7725..a9bb140 100644 --- a/drivers/mfd/ab3100-core.c +++ b/drivers/mfd/ab3100-core.c @@ -753,6 +753,7 @@ static struct mfd_cell ab3100_devs[] = { }, { .name = "ab3100-regulators", + .of_compatible = "stericsson,ab3100-regulators", .id = -1, }, { diff --git a/drivers/regulator/ab3100.c b/drivers/regulator/ab3100.c index 740735d..be1e6ad 100644 --- a/drivers/regulator/ab3100.c +++ b/drivers/regulator/ab3100.c @@ -17,6 +17,8 @@ #include #include #include +#include +#include /* LDO registers and some handy masking definitions for AB3100 */ #define AB3100_LDO_A 0x40 @@ -345,7 +347,11 @@ static int ab3100_get_voltage_regulator_external(struct regulator_dev *reg) { struct ab3100_regulator *abreg = rdev_get_drvdata(reg); - return abreg->plfdata->external_voltage; + if (abreg->plfdata) + return abreg->plfdata->external_voltage; + else + /* TODO: encode external voltage into device tree */ + return 0; } static struct regulator_ops regulator_ops_fixed = { @@ -490,6 +496,8 @@ ab3100_regulator_desc[AB3100_NUM_REGULATORS] = { static int ab3100_regulator_register(struct platform_device *pdev, struct ab3100_platform_data *plfdata, + struct regulator_init_data *init_data, + struct device_node *np, int id) { struct regulator_desc *desc; @@ -518,9 +526,11 @@ static int ab3100_regulator_register(struct platform_device *pdev, */ reg->dev = &pdev->dev; if (plfdata) { - /* This will be replaced by device tree data */ reg->plfdata = plfdata; config.init_data = &plfdata->reg_constraints[i]; + } else if (np) { + config.of_node = np; + config.init_data = init_data; } config.dev = &pdev->dev; config.driver_data = reg; @@ -540,15 +550,103 @@ static int ab3100_regulator_register(struct platform_device *pdev, return 0; } +static struct of_regulator_match ab3100_regulator_matches[] = { + { .name = "ab3100_ldo_a", .driver_data = (void *) AB3100_LDO_A, }, + { .name = "ab3100_ldo_c", .driver_data = (void *) AB3100_LDO_C, }, + { .name = "ab3100_ldo_d", .driver_data = (void *) AB3100_LDO_D, }, + { .name = "ab3100_ldo_e", .driver_data = (void *) AB3100_LDO_E, }, + { .name = "ab3100_ldo_f", .driver_data = (void *) AB3100_LDO_F }, + { .name = "ab3100_ldo_g", .driver_data = (void *) AB3100_LDO_G }, + { .name = "ab3100_ldo_h", .driver_data = (void *) AB3100_LDO_H }, + { .name = "ab3100_ldo_k", .driver_data = (void *) AB3100_LDO_K }, + { .name = "ab3100_ext", .driver_data = (void *) AB3100_LDO_EXT }, + { .name = "ab3100_buck", .driver_data = (void *) AB3100_BUCK }, +}; + /* - * NOTE: the following functions are regulators pluralis - it is the - * binding to the AB3100 core driver and the parent platform device - * for all the different regulators. + * Initial settings of ab3100 registers. + * Common for below LDO regulator settings are that + * bit 7-5 controls voltage. Bit 4 turns regulator ON(1) or OFF(0). + * Bit 3-2 controls sleep enable and bit 1-0 controls sleep mode. */ +/* LDO_A 0x16: 2.75V, ON, SLEEP_A, SLEEP OFF GND */ +#define LDO_A_SETTING 0x16 +/* LDO_C 0x10: 2.65V, ON, SLEEP_A or B, SLEEP full power */ +#define LDO_C_SETTING 0x10 +/* LDO_D 0x10: 2.65V, ON, sleep mode not used */ +#define LDO_D_SETTING 0x10 +/* LDO_E 0x10: 1.8V, ON, SLEEP_A or B, SLEEP full power */ +#define LDO_E_SETTING 0x10 +/* LDO_E SLEEP 0x00: 1.8V, not used, SLEEP_A or B, not used */ +#define LDO_E_SLEEP_SETTING 0x00 +/* LDO_F 0xD0: 2.5V, ON, SLEEP_A or B, SLEEP full power */ +#define LDO_F_SETTING 0xD0 +/* LDO_G 0x00: 2.85V, OFF, SLEEP_A or B, SLEEP full power */ +#define LDO_G_SETTING 0x00 +/* LDO_H 0x18: 2.75V, ON, SLEEP_B, SLEEP full power */ +#define LDO_H_SETTING 0x18 +/* LDO_K 0x00: 2.75V, OFF, SLEEP_A or B, SLEEP full power */ +#define LDO_K_SETTING 0x00 +/* LDO_EXT 0x00: Voltage not set, OFF, not used, not used */ +#define LDO_EXT_SETTING 0x00 +/* BUCK 0x7D: 1.2V, ON, SLEEP_A and B, SLEEP low power */ +#define BUCK_SETTING 0x7D +/* BUCK SLEEP 0xAC: 1.05V, Not used, SLEEP_A and B, Not used */ +#define BUCK_SLEEP_SETTING 0xAC + +static const u8 ab3100_reg_initvals[] = { + LDO_A_SETTING, + LDO_C_SETTING, + LDO_E_SETTING, + LDO_E_SLEEP_SETTING, + LDO_F_SETTING, + LDO_G_SETTING, + LDO_H_SETTING, + LDO_K_SETTING, + LDO_EXT_SETTING, + BUCK_SETTING, + BUCK_SLEEP_SETTING, + LDO_D_SETTING, +}; + +static int +ab3100_regulator_of_probe(struct platform_device *pdev, struct device_node *np) +{ + int err, i; + + /* + * Set up the regulator registers, as was previously done with + * platform data. + */ + /* Set up regulators */ + for (i = 0; i < ARRAY_SIZE(ab3100_reg_init_order); i++) { + err = abx500_set_register_interruptible(&pdev->dev, 0, + ab3100_reg_init_order[i], + ab3100_reg_initvals[i]); + if (err) { + dev_err(&pdev->dev, "regulator initialization failed with error %d\n", + err); + return err; + } + } + + for (i = 0; i < ARRAY_SIZE(ab3100_regulator_matches); i++) { + err = ab3100_regulator_register( + pdev, NULL, ab3100_regulator_matches[i].init_data, + ab3100_regulator_matches[i].of_node, + (int) ab3100_regulator_matches[i].driver_data); + if (err) + return err; + } + + return 0; +} + static int ab3100_regulators_probe(struct platform_device *pdev) { struct ab3100_platform_data *plfdata = pdev->dev.platform_data; + struct device_node *np = pdev->dev.of_node; int err = 0; u8 data; int i; @@ -567,6 +665,18 @@ static int ab3100_regulators_probe(struct platform_device *pdev) dev_notice(&pdev->dev, "chip is in inactive mode (Cold start)\n"); + if (np) { + err = of_regulator_match(&pdev->dev, np, + ab3100_regulator_matches, + ARRAY_SIZE(ab3100_regulator_matches)); + if (err < 0) { + dev_err(&pdev->dev, + "Error parsing regulator init data: %d\n", err); + return err; + } + return ab3100_regulator_of_probe(pdev, np); + } + /* Set up regulators */ for (i = 0; i < ARRAY_SIZE(ab3100_reg_init_order); i++) { err = abx500_set_register_interruptible(&pdev->dev, 0, @@ -583,7 +693,8 @@ static int ab3100_regulators_probe(struct platform_device *pdev) for (i = 0; i < AB3100_NUM_REGULATORS; i++) { struct regulator_desc *desc = &ab3100_regulator_desc[i]; - err = ab3100_regulator_register(pdev, plfdata, desc->id); + err = ab3100_regulator_register(pdev, plfdata, NULL, NULL, + desc->id); if (err) return err; }