From patchwork Thu Nov 5 13:34:46 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Chen Feng X-Patchwork-Id: 56048 Delivered-To: patch@linaro.org Received: by 10.112.61.134 with SMTP id p6csp415557lbr; Thu, 5 Nov 2015 05:49:04 -0800 (PST) X-Received: by 10.50.117.5 with SMTP id ka5mr3365558igb.58.1446731344193; Thu, 05 Nov 2015 05:49:04 -0800 (PST) Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id b35si6433392ioj.138.2015.11.05.05.49.03; Thu, 05 Nov 2015 05:49:04 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of devicetree-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of devicetree-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=devicetree-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1161237AbbKENtC (ORCPT + 6 others); Thu, 5 Nov 2015 08:49:02 -0500 Received: from szxga02-in.huawei.com ([119.145.14.65]:32219 "EHLO szxga02-in.huawei.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1161192AbbKENtB (ORCPT ); Thu, 5 Nov 2015 08:49:01 -0500 Received: from 172.24.1.49 (EHLO szxeml426-hub.china.huawei.com) ([172.24.1.49]) by szxrg02-dlp.huawei.com (MOS 4.3.7-GA FastPath queued) with ESMTP id CVT68618; Thu, 05 Nov 2015 21:35:09 +0800 (CST) Received: from vm163-62.huawei.com (10.184.163.62) by szxeml426-hub.china.huawei.com (10.82.67.181) with Microsoft SMTP Server id 14.3.235.1; Thu, 5 Nov 2015 21:34:58 +0800 From: Chen Feng To: , , , , , , , , , , , , , , , , , , , , , , , , CC: , , , Subject: [PATCH 5/7] regulator: add driver for mtcmos voltage regulator on hi6220 SoC Date: Thu, 5 Nov 2015 21:34:46 +0800 Message-ID: <1446730488-31930-6-git-send-email-puck.chen@hisilicon.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1446730488-31930-1-git-send-email-puck.chen@hisilicon.com> References: <1446730488-31930-1-git-send-email-puck.chen@hisilicon.com> MIME-Version: 1.0 X-Originating-IP: [10.184.163.62] X-CFilter-Loop: Reflected X-Mirapoint-Virus-RAPID-Raw: score=unknown(0), refid=str=0001.0A020202.563B5B1E.024A,ss=1,re=0.000,fgs=0, ip=0.0.0.0, so=2013-06-18 04:22:30, dmn=2011-05-27 18:58:46 X-Mirapoint-Loop-Id: 9379a3d4c801c75bdfc0e3017b96ca1d Sender: devicetree-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: devicetree@vger.kernel.org Add driver to support mtcmos on hi6220 Signed-off-by: Chen Feng Signed-off-by: Fei Wang --- drivers/regulator/hi6220-mtcmos.c | 245 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 245 insertions(+) create mode 100644 drivers/regulator/hi6220-mtcmos.c -- 1.9.1 -- To unsubscribe from this list: send the line "unsubscribe devicetree" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html diff --git a/drivers/regulator/hi6220-mtcmos.c b/drivers/regulator/hi6220-mtcmos.c new file mode 100644 index 0000000..c79ffc0 --- /dev/null +++ b/drivers/regulator/hi6220-mtcmos.c @@ -0,0 +1,245 @@ +/* + * Device driver for regulators in hi6220 mtcmos + * + * Copyright (c) 2015 Hisilicon. + * + * Fei Wang + * Chen Feng + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +enum { + HI6220_MTCMOS1, + HI6220_MTCMOS2, + HI6220_RG_MAX, +}; + +struct hi6220_mtcmos_ctrl_regs { + unsigned int enable_reg; + unsigned int disable_reg; + unsigned int status_reg; +}; + +struct hi6220_mtcmos_ctrl_data { + int shift; + unsigned int mask; +}; + +struct hi6220_mtcmos_info { + struct regulator_desc rdesc; + struct hi6220_mtcmos_ctrl_regs ctrl_regs; + struct hi6220_mtcmos_ctrl_data ctrl_data; +}; + +struct hi6220_mtcmos { + struct regulator_dev *rdev[HI6220_RG_MAX]; + void __iomem *sc_on_regs; +}; + +static int hi6220_mtcmos_is_on(struct hi6220_mtcmos *mtcmos, + unsigned int regs, unsigned int mask, int shift) +{ + unsigned int ret; + + ret = readl(mtcmos->sc_on_regs + regs); + ret &= (mask << shift); + + return ret; +} + +static int hi6220_mtcmos_is_enabled(struct regulator_dev *rdev) +{ + int ret; + struct hi6220_mtcmos_info *sreg = rdev_get_drvdata(rdev); + struct platform_device *pdev = + container_of(rdev->dev.parent, struct platform_device, dev); + struct hi6220_mtcmos *mtcmos = platform_get_drvdata(pdev); + struct hi6220_mtcmos_ctrl_regs *ctrl_regs = &sreg->ctrl_regs; + struct hi6220_mtcmos_ctrl_data *ctrl_data = &sreg->ctrl_data; + + ret = hi6220_mtcmos_is_on(mtcmos, ctrl_regs->status_reg, + ctrl_data->mask, ctrl_data->shift); + return ret; +} + +static int hi6220_mtcmos_op(struct hi6220_mtcmos *mtcmos, + unsigned int regs, unsigned int mask, int shift) +{ + writel(mask << shift, mtcmos->sc_on_regs + regs); + + return 0; +} + +static int hi6220_mtcmos_enable(struct regulator_dev *rdev) +{ + int ret; + struct hi6220_mtcmos_info *sreg = rdev_get_drvdata(rdev); + struct platform_device *pdev = + container_of(rdev->dev.parent, struct platform_device, dev); + struct hi6220_mtcmos *mtcmos = platform_get_drvdata(pdev); + struct hi6220_mtcmos_ctrl_regs *ctrl_regs = &sreg->ctrl_regs; + struct hi6220_mtcmos_ctrl_data *ctrl_data = &sreg->ctrl_data; + + hi6220_mtcmos_op(mtcmos, ctrl_regs->enable_reg, + ctrl_data->mask, ctrl_data->shift); + ret = hi6220_mtcmos_is_on(mtcmos, ctrl_regs->status_reg, + ctrl_data->mask, ctrl_data->shift) + return ret; +} + +static int hi6220_mtcmos_disable(struct regulator_dev *rdev) +{ + int ret; + struct hi6220_mtcmos_info *sreg = rdev_get_drvdata(rdev); + struct platform_device *pdev = + container_of(rdev->dev.parent, struct platform_device, dev); + struct hi6220_mtcmos *mtcmos = platform_get_drvdata(pdev); + struct hi6220_mtcmos_ctrl_regs *ctrl_regs = &sreg->ctrl_regs; + struct hi6220_mtcmos_ctrl_data *ctrl_data = &sreg->ctrl_data; + + ret = hi6220_mtcmos_op(mtcmos, ctrl_regs->disable_reg, + ctrl_data->mask, ctrl_data->shift); + + return ret; +} + +static struct regulator_ops hi6220_mtcmos_mtcmos_rops = { + .is_enabled = hi6220_mtcmos_is_enabled, + .enable = hi6220_mtcmos_enable, + .disable = hi6220_mtcmos_disable, +}; + +#define HI6220_MTCMOS(vreg) \ +{ \ + .rdesc = { \ + .name = #vreg, \ + .ops = &hi6220_mtcmos_mtcmos_rops, \ + .type = REGULATOR_VOLTAGE, \ + .owner = THIS_MODULE, \ + }, \ +} + +static struct hi6220_mtcmos_info hi6220_mtcmos_info[] = { + HI6220_MTCMOS(MTCMOS1), + HI6220_MTCMOS(MTCMOS2), +}; + +static struct of_regulator_match hi6220_mtcmos_matches[] = { + { .name = "mtcmos1", + .driver_data = &hi6220_mtcmos_info[HI6220_MTCMOS1], }, + { .name = "mtcmos2", + .driver_data = &hi6220_mtcmos_info[HI6220_MTCMOS2], }, +}; + +static int hi6220_mtcmos_probe(struct platform_device *pdev) +{ + int ret; + struct hi6220_mtcmos *mtcmos; + const __be32 *sc_on_regs = NULL; + void __iomem *regs; + struct device *dev; + struct device_node *np, *child; + int i; + struct regulator_config config = { }; + struct regulator_init_data *init_data; + struct hi6220_mtcmos_info *sreg; + u32 off_on_delay = 0; + + dev = &pdev->dev; + np = dev->of_node; + mtcmos = devm_kzalloc(dev, sizeof(struct hi6220_mtcmos), GFP_KERNEL); + if (!mtcmos) + return -ENOMEM; + + sc_on_regs = of_get_property(np, "hisilicon,mtcmos-sc-on-base", NULL); + if (sc_on_regs) { + regs = ioremap(be32_to_cpu(*sc_on_regs), SZ_4K); + mtcmos->sc_on_regs = regs; + } else + return -ENODEV; + of_property_read_u32(np, "hisilicon,mtcmos-steady-us", &off_on_delay); + + for (i = 0; i < HI6220_RG_MAX; i++) { + init_data = hi6220_mtcmos_matches[i].init_data; + if (!init_data) + continue; + sreg = hi6220_mtcmos_matches[i].driver_data; + sreg->rdesc.off_on_delay = off_on_delay; + config.dev = &pdev->dev; + config.init_data = init_data; + config.driver_data = sreg; + config.of_node = hi6220_mtcmos_matches[i].of_node; + child = config.of_node; + + ret = of_property_read_u32_array(child, "hisilicon,ctrl-regs", + (u32 *)(&sreg->ctrl_regs), + 0x3); + ret = of_property_read_u32_array(child, "hisilicon,ctrl-data", + (u32 *)(&sreg->ctrl_data), + 0x2); + + mtcmos->rdev[i] = regulator_register(&sreg->rdesc, &config); + if (IS_ERR(mtcmos->rdev[i])) { + ret = PTR_ERR(mtcmos->rdev[i]); + dev_err(&pdev->dev, "failed to register mtcmos %s\n", + sreg->rdesc.name); + while (--i >= 0) + regulator_unregister(mtcmos->rdev[i]); + + return ret; + } + } + + platform_set_drvdata(pdev, mtcmos); + + return 0; +} + +static const struct of_device_id of_hi6220_mtcmos_match_tbl[] = { + { .compatible = "hisilicon,hi6220-mtcmos-driver", }, + {} +}; + +static struct platform_driver mtcmos_driver = { + .driver = { + .name = "hisi_hi6220_mtcmos", + .owner = THIS_MODULE, + .of_match_table = of_hi6220_mtcmos_match_tbl, + }, + .probe = hi6220_mtcmos_probe, +}; + +static int __init hi6220_mtcmos_init(void) +{ + return platform_driver_register(&mtcmos_driver); +} + +static void __exit hi6220_mtcmos_exit(void) +{ + platform_driver_unregister(&mtcmos_driver); +} + +fs_initcall(hi6220_mtcmos_init); +module_exit(hi6220_mtcmos_exit); + +MODULE_AUTHOR("Fei Wang "); +MODULE_DESCRIPTION("Hi6220 mtcmos interface driver"); +MODULE_LICENSE("GPL v2");