From patchwork Sun Mar 7 18:18:48 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ying-Chun Liu X-Patchwork-Id: 395145 Delivered-To: patch@linaro.org Received: by 2002:a02:8562:0:0:0:0:0 with SMTP id g89csp1126679jai; Sun, 7 Mar 2021 10:19:28 -0800 (PST) X-Google-Smtp-Source: ABdhPJzfH5020Kr0VKwXExYUq1K6Ej6D4m17R8JUP8xLpCsDiF6zcjTcJy7ygidJsHPeuPHhH+qT X-Received: by 2002:a50:f391:: with SMTP id g17mr18721094edm.26.1615141168699; Sun, 07 Mar 2021 10:19:28 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1615141168; cv=none; d=google.com; s=arc-20160816; b=lEMZ6WdQIL9XXfvBMhnqpsf88UFD+n5kiCRT/ueSj6SMp/mxON/9CBJU0dSkOn27Z+ dOxaA9UAy10Fc4iWnZ8A5n2hTO9xPr5YMbOUp9G+TTjwOz0EfP7Fs4xCwWReKOC+ac0J ZwdANsiA/wtzhYRu7zab8JWr48CHJFpdFRc9hU3sZz3DrMs6R0klhjKZ/yJW34MNS63I b6iFhtwuGqqrE/nM1OPonWmZWmuWjRP6f6nh+jrd1mNNmnRYZnzF+IUo/wC32ODFYfA/ yG8CqU74LKGlv3C6LHBkJCcK2iLlVRV+Y5IHdtaFt9/kYpam9ekJ1XDJ7NaZZVtUgXmF IaeA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:list-subscribe:list-help:list-post:list-archive :list-unsubscribe:list-id:precedence:content-transfer-encoding :mime-version:references:in-reply-to:message-id:date:subject:cc:to :from:dkim-signature; bh=dQabQFIPc4rQCmqb8NPj2eaV+ZB6HmOi3UN9Wy/7w3w=; b=VgHs8D4a47ndcNEMZvdfTgu7hOEiHN303fHz1YCsvqPwPnEpvH+hZBJqSctfXTA+7P lbwjzwTW3b+SH2x4eFSxKcanfSSMa+l6Ykp1GiZaibs+E5rJmAHxS++p1ALBJJVOo973 hARUJqWZH9U6Ukhxkv+JrYnUOWhByI8pSeRg7qgm9NWwFdVYxgXtWvRXrqY6W3233NlN J8KPbaVhdvSxJ8Ms3lUrLZzD8EkUobaJSg1Ly/TlxqDrrzS7Po9pUTTVeuIJH1OxNHQQ bTeJrA2DiHl0r4rn5tVxpdjIfcoYE30K0jf2n+KGLBH2G32tSqtyiFSTBEpIuR0a9UeC Wiqg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@gmail.com header.s=20161025 header.b=Df8VBjGM; spf=pass (google.com: domain of u-boot-bounces@lists.denx.de designates 2a01:238:438b:c500:173d:9f52:ddab:ee01 as permitted sender) smtp.mailfrom=u-boot-bounces@lists.denx.de; dmarc=pass (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Return-Path: Received: from phobos.denx.de (phobos.denx.de. [2a01:238:438b:c500:173d:9f52:ddab:ee01]) by mx.google.com with ESMTPS id o13si5419367eje.367.2021.03.07.10.19.28 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 07 Mar 2021 10:19:28 -0800 (PST) Received-SPF: pass (google.com: domain of u-boot-bounces@lists.denx.de designates 2a01:238:438b:c500:173d:9f52:ddab:ee01 as permitted sender) client-ip=2a01:238:438b:c500:173d:9f52:ddab:ee01; Authentication-Results: mx.google.com; dkim=pass header.i=@gmail.com header.s=20161025 header.b=Df8VBjGM; spf=pass (google.com: domain of u-boot-bounces@lists.denx.de designates 2a01:238:438b:c500:173d:9f52:ddab:ee01 as permitted sender) smtp.mailfrom=u-boot-bounces@lists.denx.de; dmarc=pass (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 2ACEF8278B; Sun, 7 Mar 2021 19:19:19 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="Df8VBjGM"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 39F2B82790; Sun, 7 Mar 2021 19:19:17 +0100 (CET) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-2.0 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FROM,SPF_HELO_NONE autolearn=ham autolearn_force=no version=3.4.2 Received: from mail-pg1-x536.google.com (mail-pg1-x536.google.com [IPv6:2607:f8b0:4864:20::536]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id A3BA8826AC for ; Sun, 7 Mar 2021 19:19:13 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=grandpaul@gmail.com Received: by mail-pg1-x536.google.com with SMTP id w34so3869637pga.8 for ; Sun, 07 Mar 2021 10:19:13 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=dQabQFIPc4rQCmqb8NPj2eaV+ZB6HmOi3UN9Wy/7w3w=; b=Df8VBjGMQcdhtn6CMVq15cyRwrWQDwlBEkH5qlXXTFl+OyJYBSuuQx1FEWXGXA/zAI FyUd0DCZFtqUvT92bPlQ0uzn7l2a/WVOagsnIgyGkKhgkmUX37O0B2rWfc6GIND+aahA 0ZJjBtBXy30WZREbS0r/t1XgQAG+Wxc0TMH6PxjG8ZVRBnmQNtgoahwpEv4p5Nr+hWAC OWLa3TOUEEV/aHCfud5lhH4CnFE21rRRhIllRjveO85XlNTNLgwsM5kkU3l6MwE8Y4c9 IbkGfUPZYripFcWM0P2DesUVMJ2XaG+T3PZbUnmHEhT2U0NDGtUMnS1fOQMGqW7pRDXx REyw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=dQabQFIPc4rQCmqb8NPj2eaV+ZB6HmOi3UN9Wy/7w3w=; b=SmJQYuDF8vk/VNt7yJ0UHgyqU5PekZACCM+gfYygtMrOvbBE+uAu1u09MPE65QMvcm lYQRmXrv+Hc5qD9L24Cr1I9swmgeShQKimPLPRW6gSvARHit+bgrYdAVCFhmDvChQLNJ hjabmypKifjgLxy+64LpwxKvZC7CZYyani2JbLskhAkWQ/ZkIvCsbutOPQccGc9MBK93 Y5cGuq6AN43HuB3S2kQaakPTIIZ65nJoU30fBMS87pE/WZqWHI12HmZRebcsm8cGgUUo Awd8PiddkTqr0rcqcE8CfXB+yd6/ZwlDYOT3/O/nz1PJfHhMbkhtALtdrpA+9zAPR3aO fwTw== X-Gm-Message-State: AOAM532YJ8H2X+Z/hHGoElQRewhaOp26e9zmRz3wWeYapGDHcxMWPrmE 7OaoLKEz0xiOs9okVKLK4UE9xvq/QdI= X-Received: by 2002:a63:e84f:: with SMTP id a15mr17145226pgk.249.1615141151703; Sun, 07 Mar 2021 10:19:11 -0800 (PST) Received: from localhost (host-111-184-129-17.dynamic.kbtelecom.net. [111.184.129.17]) by smtp.gmail.com with ESMTPSA id v134sm7974368pfc.182.2021.03.07.10.19.11 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 07 Mar 2021 10:19:11 -0800 (PST) From: Ying-Chun Liu To: u-boot@lists.denx.de Cc: "Ying-Chun Liu (PaulLiu)" Subject: [PATCH 1/2] power: regulator: add driver for ANATOP regulator Date: Mon, 8 Mar 2021 02:18:48 +0800 Message-Id: <20210307181849.83627-2-grandpaul@gmail.com> X-Mailer: git-send-email 2.30.1 In-Reply-To: <20210307181849.83627-1-grandpaul@gmail.com> References: <20210307181849.83627-1-grandpaul@gmail.com> MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.34 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.102.4 at phobos.denx.de X-Virus-Status: Clean From: "Ying-Chun Liu (PaulLiu)" Anatop is an integrated regulator inside i.MX6 SoC. There are 3 digital regulators which controls PU, CORE (ARM), and SOC. And 3 analog regulators which controls 1P1, 2P5, 3P0 (USB). This patch adds the Anatop regulator driver. Signed-off-by: Ying-Chun Liu (PaulLiu) --- drivers/power/regulator/Kconfig | 10 + drivers/power/regulator/Makefile | 1 + drivers/power/regulator/anatop_regulator.c | 289 +++++++++++++++++++++ 3 files changed, 300 insertions(+) create mode 100644 drivers/power/regulator/anatop_regulator.c -- 2.30.1 diff --git a/drivers/power/regulator/Kconfig b/drivers/power/regulator/Kconfig index fbbea18c7d..1cd1f3f5ed 100644 --- a/drivers/power/regulator/Kconfig +++ b/drivers/power/regulator/Kconfig @@ -312,6 +312,16 @@ config DM_REGULATOR_STPMIC1 by the PMIC device. This driver is controlled by a device tree node which includes voltage limits. +config DM_REGULATOR_ANATOP + bool "Enable driver for ANATOP regulators" + depends on DM_REGULATOR + select REGMAP + select SYSCON + help + Enable support for the Freescale i.MX on-chip ANATOP LDOs + regulators. It is recommended that this option be enabled on + i.MX6 platform. + config SPL_DM_REGULATOR_STPMIC1 bool "Enable driver for STPMIC1 regulators in SPL" depends on SPL_DM_REGULATOR && PMIC_STPMIC1 diff --git a/drivers/power/regulator/Makefile b/drivers/power/regulator/Makefile index 9d58112dcb..e7198da911 100644 --- a/drivers/power/regulator/Makefile +++ b/drivers/power/regulator/Makefile @@ -30,3 +30,4 @@ obj-$(CONFIG_DM_REGULATOR_TPS65910) += tps65910_regulator.o obj-$(CONFIG_DM_REGULATOR_TPS62360) += tps62360_regulator.o obj-$(CONFIG_$(SPL_)DM_REGULATOR_STPMIC1) += stpmic1.o obj-$(CONFIG_DM_REGULATOR_TPS65941) += tps65941_regulator.o +obj-$(CONFIG_$(SPL_)DM_REGULATOR_ANATOP) += anatop_regulator.o diff --git a/drivers/power/regulator/anatop_regulator.c b/drivers/power/regulator/anatop_regulator.c new file mode 100644 index 0000000000..2bb5cdbac5 --- /dev/null +++ b/drivers/power/regulator/anatop_regulator.c @@ -0,0 +1,289 @@ +// SPDX-License-Identifier: GPL-2.0+ +// +// Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved. +// Copyright (C) 2021 Linaro + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define LDO_RAMP_UP_UNIT_IN_CYCLES 64 /* 64 cycles per step */ +#define LDO_RAMP_UP_FREQ_IN_MHZ 24 /* cycle based on 24M OSC */ + +#define LDO_POWER_GATE 0x00 +#define LDO_FET_FULL_ON 0x1f + +struct anatop_regulator { + const char *name; + u32 control_reg; + u32 vol_bit_shift; + u32 vol_bit_width; + u32 min_bit_val; + u32 min_voltage; + u32 max_voltage; + u32 delay_reg; + u32 delay_bit_shift; + u32 delay_bit_width; +}; + +static u32 anatop_get_bits(struct udevice *dev, u32 addr, int bit_shift, + int bit_width) +{ + struct udevice *syscon; + struct regmap *regmap; + int err; + u32 val, mask; + + syscon = dev_get_parent(dev); + if (!syscon) { + dev_err(dev, "%s: unable to find syscon device\n", __func__); + return err; + } + + regmap = syscon_get_regmap(syscon); + if (IS_ERR(regmap)) { + dev_err(dev, "%s: unable to find regmap (%ld)\n", __func__, + PTR_ERR(regmap)); + return PTR_ERR(regmap); + } + + if (bit_width == 32) + mask = ~0; + else + mask = (1 << bit_width) - 1; + + err = regmap_read(regmap, addr, &val); + if (err) + return err; + + val = (val >> bit_shift) & mask; + + return val; +} + +void anatop_set_bits(struct udevice *dev, u32 addr, int bit_shift, + int bit_width, u32 data) +{ + struct udevice *syscon; + struct regmap *regmap; + int err; + u32 val, mask; + + syscon = dev_get_parent(dev); + if (!syscon) { + dev_err(dev, "%s: unable to find syscon device\n", __func__); + return; + } + + regmap = syscon_get_regmap(syscon); + if (IS_ERR(regmap)) { + dev_err(dev, + "%s: unable to find regmap (%ld)\n", __func__, + PTR_ERR(regmap)); + return; + } + + if (bit_width == 32) + mask = ~0; + else + mask = (1 << bit_width) - 1; + + err = regmap_read(regmap, addr, &val); + if (err) { + dev_err(dev, + "%s: cannot read reg (%d)\n", __func__, + err); + return; + } + val = val & ~(mask << bit_shift); + err = regmap_write(regmap, addr, (data << bit_shift) | val); + if (err) { + dev_err(dev, + "%s: cannot wrie reg (%d)\n", __func__, + err); + return; + } +} + +static int anatop_set_voltage(struct udevice *dev, int uV) +{ + const struct anatop_regulator *anatop_reg = dev_get_plat(dev); + u32 val; + u32 sel; + int delayus = 0; + int ret = 0; + int uv; + + uv = uV; + dev_dbg(dev, "%s: uv %d, min %d, max %d\n", __func__, + uv, anatop_reg->min_voltage, + anatop_reg->max_voltage); + + if (uv < anatop_reg->min_voltage) + return -EINVAL; + + if (!anatop_reg->control_reg) + return -ENOTSUPP; + + sel = DIV_ROUND_UP(uv - anatop_reg->min_voltage, 25000); + if (sel * 25000 + anatop_reg->min_voltage > anatop_reg->max_voltage) + return -EINVAL; + val = anatop_reg->min_bit_val + sel; + dev_dbg(dev, "%s: calculated val %d\n", __func__, val); + + /* check whether need to care about LDO ramp up speed */ + if (anatop_reg->delay_bit_width) { + /* + * the delay for LDO ramp up time is + * based on the register setting, we need + * to calculate how many steps LDO need to + * ramp up, and how much delay needed. (us) + */ + u32 old_sel; + u32 new_sel = sel; + + old_sel = anatop_get_bits(dev, + anatop_reg->control_reg, + anatop_reg->vol_bit_shift, + anatop_reg->vol_bit_width); + old_sel = old_sel - anatop_reg->min_bit_val; + + if (new_sel > old_sel) { + val = anatop_get_bits(dev, + anatop_reg->delay_reg, + anatop_reg->delay_bit_shift, + anatop_reg->delay_bit_width); + delayus = (new_sel - old_sel) * + (LDO_RAMP_UP_UNIT_IN_CYCLES << val) / + LDO_RAMP_UP_FREQ_IN_MHZ + 1; + } + } + + anatop_set_bits(dev, + anatop_reg->control_reg, + anatop_reg->vol_bit_shift, + anatop_reg->vol_bit_width, + val); + + if (delayus) + udelay(delayus); + + return ret; +} + +static int anatop_get_voltage(struct udevice *dev) +{ + const struct anatop_regulator *anatop_reg = dev_get_plat(dev); + u32 val; + u32 sel; + + val = anatop_get_bits(dev, + anatop_reg->control_reg, + anatop_reg->vol_bit_shift, + anatop_reg->vol_bit_width); + sel = val - anatop_reg->min_bit_val; + + return sel * 25000 + anatop_reg->min_voltage; +} + +static const struct dm_regulator_ops anatop_regulator_ops = { + .set_value = anatop_set_voltage, + .get_value = anatop_get_voltage, +}; + +static int anatop_regulator_probe(struct udevice *dev) +{ + struct anatop_regulator *sreg; + int ret = 0; + + sreg = dev_get_plat(dev); + if (!sreg) { + dev_err(dev, "failed to get plat data\n"); + return -ENOMEM; + } + + sreg->name = ofnode_read_string(dev_ofnode(dev), "regulator-name"); + if (!sreg->name) { + dev_err(dev, "failed to get a regulator-name\n"); + return -EINVAL; + } + + ret = ofnode_read_u32(dev_ofnode(dev), + "anatop-reg-offset", + &sreg->control_reg); + if (ret) { + dev_err(dev, "no anatop-reg-offset property set\n"); + return ret; + } + ret = ofnode_read_u32(dev_ofnode(dev), + "anatop-vol-bit-width", + &sreg->vol_bit_width); + if (ret) { + dev_err(dev, "no anatop-vol-bit-width property set\n"); + return ret; + } + ret = ofnode_read_u32(dev_ofnode(dev), + "anatop-vol-bit-shift", + &sreg->vol_bit_shift); + if (ret) { + dev_err(dev, "no anatop-vol-bit-shift property set\n"); + return ret; + } + ret = ofnode_read_u32(dev_ofnode(dev), + "anatop-min-bit-val", + &sreg->min_bit_val); + if (ret) { + dev_err(dev, "no anatop-min-bit-val property set\n"); + return ret; + } + ret = ofnode_read_u32(dev_ofnode(dev), + "anatop-min-voltage", + &sreg->min_voltage); + if (ret) { + dev_err(dev, "no anatop-min-voltage property set\n"); + return ret; + } + ret = ofnode_read_u32(dev_ofnode(dev), + "anatop-max-voltage", + &sreg->max_voltage); + if (ret) { + dev_err(dev, "no anatop-max-voltage property set\n"); + return ret; + } + + /* read LDO ramp up setting, only for core reg */ + ofnode_read_u32(dev_ofnode(dev), "anatop-delay-reg-offset", + &sreg->delay_reg); + ofnode_read_u32(dev_ofnode(dev), "anatop-delay-bit-width", + &sreg->delay_bit_width); + ofnode_read_u32(dev_ofnode(dev), "anatop-delay-bit-shift", + &sreg->delay_bit_shift); + + return 0; +} + +static const struct udevice_id of_anatop_regulator_match_tbl[] = { + { .compatible = "fsl,anatop-regulator", }, + { /* end */ } +}; + +U_BOOT_DRIVER(anatop_regulator) = { + .name = "anatop_regulator", + .id = UCLASS_REGULATOR, + .ops = &anatop_regulator_ops, + .of_match = of_anatop_regulator_match_tbl, + .plat_auto = sizeof(struct anatop_regulator), + .probe = anatop_regulator_probe, +};