From patchwork Wed Sep 30 11:05:10 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Fei Wang X-Patchwork-Id: 54306 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-wi0-f200.google.com (mail-wi0-f200.google.com [209.85.212.200]) by patches.linaro.org (Postfix) with ESMTPS id A008022E23 for ; Wed, 30 Sep 2015 11:22:31 +0000 (UTC) Received: by wicmn1 with SMTP id mn1sf20638527wic.1 for ; Wed, 30 Sep 2015 04:22:30 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:delivered-to:from:to:cc:subject:date:message-id :in-reply-to:references:mime-version:content-type:sender:precedence :list-id:x-original-sender:x-original-authentication-results :mailing-list:list-post:list-help:list-archive:list-unsubscribe; bh=+Z+tpRPtoP81uip8Dp5wscOwJlFFFTfb+L+iEqeJoww=; b=jYzc2IbgVb3Z0y6/OkA3p8j3bpQKQPldFuAqNO+btEg/pjJBCifHVy04RKLDs/vpzJ Md7MmRUV/52T0Y6I+hcFK2myJjzZFOI9dVRYNPHyJbBkMeGDULfA62XyuTNX+f0PP5ol zuIxnhFcjqyfImfem75YbzrYbUrkNyWp0Iw9OqxdbBcRkihUZXkeLT8GNlQx42V/GsO0 qvnxM3Agi1j3D1aofNR8RnUlz1HxUHghX3JE4a+Rhyikm2mqb3eRchXQpgqRlCcAg/py W5l8VbrTpxrzX0nVmtBvqG+CzW5SxG+LzLt/aePigKZwOU/S8Sqw+j+mtbwkDc7AAjAk l/vw== X-Gm-Message-State: ALoCoQmvaFrw6MA1St6aEYKjVSTrhgV3cefDdMTrIKHVoFiOx2eTqMUU6zWbHK5gYrPA6gyCboY5 X-Received: by 10.112.164.1 with SMTP id ym1mr443575lbb.15.1443612150896; Wed, 30 Sep 2015 04:22:30 -0700 (PDT) X-BeenThere: patchwork-forward@linaro.org Received: by 10.152.198.202 with SMTP id je10ls35464lac.5.gmail; Wed, 30 Sep 2015 04:22:30 -0700 (PDT) X-Received: by 10.112.137.169 with SMTP id qj9mr966725lbb.34.1443612150758; Wed, 30 Sep 2015 04:22:30 -0700 (PDT) Received: from mail-la0-f46.google.com (mail-la0-f46.google.com. [209.85.215.46]) by mx.google.com with ESMTPS id x128si33303lfd.127.2015.09.30.04.22.30 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 30 Sep 2015 04:22:30 -0700 (PDT) Received-SPF: pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 209.85.215.46 as permitted sender) client-ip=209.85.215.46; Received: by labzv5 with SMTP id zv5so42072685lab.1 for ; Wed, 30 Sep 2015 04:22:30 -0700 (PDT) X-Received: by 10.112.151.106 with SMTP id up10mr936067lbb.106.1443612150419; Wed, 30 Sep 2015 04:22:30 -0700 (PDT) X-Forwarded-To: patchwork-forward@linaro.org X-Forwarded-For: patch@linaro.org patchwork-forward@linaro.org Delivered-To: patch@linaro.org Received: by 10.112.59.35 with SMTP id w3csp2688121lbq; Wed, 30 Sep 2015 04:22:29 -0700 (PDT) X-Received: by 10.68.218.137 with SMTP id pg9mr4423030pbc.160.1443612149251; Wed, 30 Sep 2015 04:22:29 -0700 (PDT) Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id ez3si119524pab.130.2015.09.30.04.22.29; Wed, 30 Sep 2015 04:22:29 -0700 (PDT) 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; Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S932661AbbI3LW1 (ORCPT + 7 others); Wed, 30 Sep 2015 07:22:27 -0400 Received: from szxga03-in.huawei.com ([119.145.14.66]:15538 "EHLO szxga03-in.huawei.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S932338AbbI3LW0 (ORCPT ); Wed, 30 Sep 2015 07:22:26 -0400 Received: from 172.24.1.50 (EHLO szxeml431-hub.china.huawei.com) ([172.24.1.50]) by szxrg03-dlp.huawei.com (MOS 4.4.3-GA FastPath queued) with ESMTP id BOE86775; Wed, 30 Sep 2015 19:05:24 +0800 (CST) Received: from localhost (10.67.54.136) by szxeml431-hub.china.huawei.com (10.82.67.208) with Microsoft SMTP Server id 14.3.235.1; Wed, 30 Sep 2015 19:05:14 +0800 From: Fei Wang To: , , , , , , , , , , , , , , CC: , , , , , , , , , , , , Subject: [PATCH 7/8] mtcmos: Hi6220: Add Hi6220 mtcmos regulator driver Date: Wed, 30 Sep 2015 19:05:10 +0800 Message-ID: <1443611111-3196-8-git-send-email-w.f@huawei.com> X-Mailer: git-send-email 2.6.0.windows.1 In-Reply-To: <1443611111-3196-1-git-send-email-w.f@huawei.com> References: <1443611111-3196-1-git-send-email-w.f@huawei.com> MIME-Version: 1.0 X-Originating-IP: [10.67.54.136] X-CFilter-Loop: Reflected X-Mirapoint-Virus-RAPID-Raw: score=unknown(0), refid=str=0001.0A090201.560BC1F5.0101, ss=1, re=0.000, recu=0.000, reip=0.000, cl=1, cld=1, fgs=0, ip=0.0.0.0, so=2013-05-26 15:14:31, dmn=2013-03-21 17:37:32 X-Mirapoint-Loop-Id: 7a808a725dc8cba6596fc2d87f2c9bdf Sender: devicetree-owner@vger.kernel.org Precedence: list List-ID: X-Mailing-List: devicetree@vger.kernel.org X-Removed-Original-Auth: Dkim didn't pass. X-Original-Sender: w.f@huawei.com X-Original-Authentication-Results: mx.google.com; spf=pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 209.85.215.46 as permitted sender) smtp.mailfrom=patch+caf_=patchwork-forward=linaro.org@linaro.org Mailing-list: list patchwork-forward@linaro.org; contact patchwork-forward+owners@linaro.org X-Google-Group-Id: 836684582541 List-Post: , List-Help: , List-Archive: List-Unsubscribe: , Add Hi6220 mtcmos regulator driver. Signed-off-by: Fei Wang --- drivers/regulator/Kconfig | 8 ++ drivers/regulator/Makefile | 1 + drivers/regulator/hi6220-mtcmos.c | 281 +++++++++++++++++++++++++++++++++++++ 3 files changed, 290 insertions(+) create mode 100644 drivers/regulator/hi6220-mtcmos.c diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig index d13210b..b5af2c6 100644 --- a/drivers/regulator/Kconfig +++ b/drivers/regulator/Kconfig @@ -269,6 +269,14 @@ config REGULATOR_HI655X This driver provides support for the voltage regulators of the Hisilicon Hi655x PMIC device. +config REGULATOR_HI6220 + tristate "Hisilicon Hi6220 MTCMOS regulator support" + depends on ARCH_HISI + default ARCH_HISI + help + This driver provides support for the mtcmos regulators on the + Hisilicon Hi6220 chip. + config REGULATOR_ISL9305 tristate "Intersil ISL9305 regulator" depends on I2C diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile index 8e4db96..0590e8f 100644 --- a/drivers/regulator/Makefile +++ b/drivers/regulator/Makefile @@ -35,6 +35,7 @@ obj-$(CONFIG_REGULATOR_FAN53555) += fan53555.o obj-$(CONFIG_REGULATOR_GPIO) += gpio-regulator.o obj-$(CONFIG_REGULATOR_HI6421) += hi6421-regulator.o obj-$(CONFIG_REGULATOR_HI655X) += hi655x-regulator.o +obj-$(CONFIG_REGULATOR_HI6220) += hi6220-mtcmos.o obj-$(CONFIG_REGULATOR_ISL6271A) += isl6271a-regulator.o obj-$(CONFIG_REGULATOR_ISL9305) += isl9305.o obj-$(CONFIG_REGULATOR_LP3971) += lp3971.o diff --git a/drivers/regulator/hi6220-mtcmos.c b/drivers/regulator/hi6220-mtcmos.c new file mode 100644 index 0000000..4e84843 --- /dev/null +++ b/drivers/regulator/hi6220-mtcmos.c @@ -0,0 +1,281 @@ +/* + * Device driver for MTCMOS DRIVER in hi6220 SOC + * + * Copyright (c) 2015 Hisilicon Co. Ltd + * + * Fei Wang + * + * 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. + * + * This program is distributed in the hope that 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. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#include +#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; + int mtcmos_steady_time; + spinlock_t mtcmos_spin_lock; +}; + +static int hi6220_mtcmos_is_on(struct hi6220_mtcmos *mtcmos, + unsigned int regs, unsigned int mask, int shift) +{ + unsigned int ret; + unsigned long mtcmos_spin_flag = 0; + + spin_lock_irqsave(&mtcmos->mtcmos_spin_lock, mtcmos_spin_flag); + ret = readl(mtcmos->sc_on_regs + regs); + spin_unlock_irqrestore(&mtcmos->mtcmos_spin_lock, mtcmos_spin_flag); + + ret &= (mask << shift); + return !!ret; +} + +int hi6220_mtcmos_on(struct hi6220_mtcmos *mtcmos, + unsigned int regs, unsigned int mask, int shift) +{ + unsigned long mtcmos_spin_flag = 0; + + spin_lock_irqsave(&mtcmos->mtcmos_spin_lock, mtcmos_spin_flag); + writel(mask << shift, mtcmos->sc_on_regs + regs); + udelay(mtcmos->mtcmos_steady_time); + spin_unlock_irqrestore(&mtcmos->mtcmos_spin_lock, mtcmos_spin_flag); + + return 0; +} + +int hi6220_mtcmos_off(struct hi6220_mtcmos *mtcmos, + unsigned int regs, unsigned int mask, int shift) +{ + unsigned long mtcmos_spin_flag = 0; + + spin_lock_irqsave(&mtcmos->mtcmos_spin_lock, mtcmos_spin_flag); + writel(mask << shift, mtcmos->sc_on_regs + regs); + udelay(mtcmos->mtcmos_steady_time); + spin_unlock_irqrestore(&mtcmos->mtcmos_spin_lock, + mtcmos_spin_flag); + + return 0; +} + +static int hi6220_regulator_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_regulator_mtcmos_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_on(mtcmos, ctrl_regs->enable_reg, + ctrl_data->mask, ctrl_data->shift); + if (0 == hi6220_mtcmos_is_on(mtcmos, ctrl_regs->status_reg, + ctrl_data->mask, ctrl_data->shift)) { + return -1; + } + return ret; +} + +static int hi6220_regulator_mtcmos_disabled(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_off(mtcmos, ctrl_regs->disable_reg, + ctrl_data->mask, ctrl_data->shift); + + return ret; +} + +static struct regulator_ops hi6220_mtcmos_mtcmos_rops = { + .is_enabled = hi6220_regulator_mtcmos_is_enabled, + .enable = hi6220_regulator_mtcmos_enabled, + .disable = hi6220_regulator_mtcmos_disabled, +}; + +#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 count, i; + struct regulator_config config = { }; + struct regulator_init_data *init_data; + struct hi6220_mtcmos_info *sreg; + + dev = &pdev->dev; + np = dev->of_node; + mtcmos = devm_kzalloc(dev, + sizeof(struct hi6220_mtcmos), GFP_KERNEL); + if (!mtcmos) + return -ENOMEM; + + spin_lock_init((spinlock_t *)&mtcmos->mtcmos_spin_lock); + 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), 0x1000); + mtcmos->sc_on_regs = regs; + } + ret = of_property_read_u32(np, "hisilicon,mtcmos-steady-us", + &mtcmos->mtcmos_steady_time); + + count = of_regulator_match(&pdev->dev, np, + hi6220_mtcmos_matches, + ARRAY_SIZE(hi6220_mtcmos_matches)); + + 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; + 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", + (unsigned int *)(&sreg->ctrl_regs), 0x3); + ret = of_property_read_u32_array(child, "hisilicon,ctrl-data", + (unsigned int *)(&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 mtcmo interface driver"); +MODULE_LICENSE("GPL v2");