From patchwork Thu Sep 10 10:44:39 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jerome Brunet X-Patchwork-Id: 3271 Return-Path: X-Original-To: noreply@patchwork.local Delivered-To: noreply@patchwork.local Received: from sin.lore.kernel.org (sin.lore.kernel.org [104.64.211.4]) by mxe881.netcup.net (Postfix) with ESMTPS id 1F95B1C2BFD for ; Thu, 10 Sep 2026 13:02:48 +0200 (CEST) Authentication-Results: mxe881; dkim=pass header.d=baylibre.com; spf=pass (sender IP is 104.64.211.4) smtp.mailfrom=linux-sunxi+bounces-25790-noreply=patchwork.local@lists.linux.dev smtp.helo=sin.lore.kernel.org Received-SPF: pass (mxe881: domain of lists.linux.dev designates 104.64.211.4 as permitted sender) client-ip=104.64.211.4; envelope-from=linux-sunxi+bounces-25790-noreply=patchwork.local@lists.linux.dev; helo=sin.lore.kernel.org; Received: from smtp.subspace.kernel.org (conduit.subspace.kernel.org [100.90.174.1]) by sin.lore.kernel.org (Postfix) with ESMTP id 6684F2A761 for ; Thu, 10 Sep 2026 10:45:45 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 7D18D46AA64; Thu, 10 Sep 2026 10:45:04 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=baylibre.com header.i=@baylibre.com header.b="hB5JKsij" X-Original-To: linux-sunxi@lists.linux.dev Received: from mail-wr2-f12.google.com (mail-wr2-f12.google.com [74.125.225.76]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 92A8D45D92C for ; Thu, 10 Sep 2026 10:44:58 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=74.125.225.76 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789037104; cv=none; b=pXOsSIWC38lxASlyRRvRdRyM3fmLosIWuUkznwdC4YT8oGm8dJoLCcmXKaITXbCHLSOPg8ciAqBeHMIJNjQV+7glqnQrk+atYmFXf3FcDkVOVcm6H8omOMW32MXrt2mf1fLYKs0zPbIXkP+Xch5F/meoiTwrPPIPO60M5uutT9g= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789037104; c=relaxed/simple; bh=HxfOQgxeNC2M/0FZuUE7U8uVbNE1FfEV8GtT6PXgiCc=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=eY4olyj3ZAB8cs2hpJhpUq9a2GuySR8HDpJEvxdzejZdR9gAZ+7Jb59RFhwjP8/fe0+rQjG82DN6MIsmVEvYNvzPGar12IuGI9qoHJL66SR11qSC2VOiNnJu1ObDuGO+zYBblKGhvFzYslb6b+52rhpHacVq+xiYxEKzbXnfjP4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=baylibre.com; spf=pass smtp.mailfrom=baylibre.com; dkim=pass (2048-bit key) header.d=baylibre.com header.i=@baylibre.com header.b=hB5JKsij; arc=none smtp.client-ip=74.125.225.76 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=baylibre.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=baylibre.com Received: by mail-wr2-f12.google.com with SMTP id ffacd0b85a97d-485b1d2874aso1026120f8f.1 for ; Thu, 10 Sep 2026 03:44:58 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=baylibre.com; s=google; t=1789037096; x=1789641896; darn=lists.linux.dev; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=9frimrJtum7yK2qZWoLc4swbgstoZT3xwJT/qEIOZUI=; b=hB5JKsijFo8dxT2rUDIEQs/+TBcHmJtWhN5+9txSNg36gY9UPNRIVla5prLU4Z90uc o6fISETw9yO95l13XOf+o+OBQ3aYLJGOnmk1vfJb2w/n6Z4wM4a6IjIZMsCVGVBAPbTC nlIc+eSAgAjw6rEEtmxenlY+ra2yciBXF5ARMTh87cgTbFuxGvtIVWUljeSeIbeHkEWM jRCZyPzfcOaI2ObvGOGd8SxmJKfE39jSNXWb1pOYyAo17/NpLeshVQnGQCI3Rq7jg6B5 9ypYtbdDw6wSOOOU5i04PC+yJUWviITNT4vc41uPson7FHD9kHhlXkaLc31a4Y5e6ZKQ wEGA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1789037096; x=1789641896; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to :content-type; bh=9frimrJtum7yK2qZWoLc4swbgstoZT3xwJT/qEIOZUI=; b=i4HhrRF99PMYT8f30Cn018bejXUMve5fvLDm1GN9Vx1M1Q3xUEd89yCnUBW48/5FJM CFDlViAerS/KjdrmOCprbA4aSp4Nk8mL34V7rLj5ptHH3mJwYDNbxmCGahPWoZVBvglf LBbz61s9jiqaj0GDNym2OfprJHfCHTgMkaPp+cxDumuZseOuWKGS9ZWBluBljdduyXc2 BWgRxwmyyVwea6tzBDgXEO9TORgrPXQcQAvRgeWLbZPF20H3MFzk8YrWLr81CMG0CILD Lvf5Wzi5qg0GxmCrdlWsj3bsShINsgXMc7dL5LN7q98XIwxHsuTdgzccNyPoxC5T28ry JEuQ== X-Forwarded-Encrypted: i=1; AKwUvByqrMRHJzq3p9iaCACY2hr9Ykal5i83XoU4B706lD5NLOoQkA0pxJyUje6jc/64/7AMy6+htAnLeYBSjQ==@lists.linux.dev X-Gm-Message-State: AFuF++mq2JTAavpyBq6Xf+G3PlRwDjwVmeneraq+xz/GjUMpkioVp3fJ lhPnt7GCWzPdPNhvbOrOs0gzX920aoUCGjSWlMDhQYL7aGX0qBmIgsCpsjEu5yDS/dI= X-Gm-Gg: AYBFou0JTz/3K5bYWjTZALps7uAm/Qesxn0KOty1+zzUHpPxBt9PdHPoNmdrTLQwt3a QABxNIqiTVYKwoG+uaJ7Tan4cCyaHkq7CsOAsvA0sF9EJsAUR7camFxPhmuMQAhJzQsSW7+LyXT pNUzueCPP70r/qQNVorErjIRbdSFWdBYRJdEYEjx4Kr88Su+zvnEuj1MCn84oM2er2wkLgTDLDK mIpKJ3Iqk7EzvTqLHLxCTBFDxc4gPagMbGaqWl1ukjUkCuTn3ug4ieNKtJSOL/HLK8paRglGP8u E9w7BlgKB04w6Z5xZjOId+2HW6iSLuzuQZKw/sfCpJPHPMydG5yAuHUF4fIQs1IPIV4OCv/ZhDH +Xn6MxIGuf6KC8b0rM9iaN5meUL3OfGJ5C8EWvuAxWpH/wxV8gYJNfa5H5bpvLu8qX9wy4iAJci 6cnsedHNfbWoRxUDj2YAXVnqSmF3z/iMrqmyU1GUr9fvE2uUj+/cqHUHvO7KeuK76EgiqcdRU7T PMEQffk0w7i2qtG9Q== X-Received: by 2002:a05:6000:430e:b0:482:ea08:8c8a with SMTP id ffacd0b85a97d-485c23e5411mr11946509f8f.20.1789037095733; Thu, 10 Sep 2026 03:44:55 -0700 (PDT) Received: from localhost (82-67-6-57.subs.proxad.net. [82.67.6.57]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-485885bf3f0sm55469516f8f.33.2026.09.10.03.44.55 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 10 Sep 2026 03:44:55 -0700 (PDT) From: Jerome Brunet Date: Thu, 10 Sep 2026 12:44:39 +0200 Subject: [PATCH v8 5/5] regulator: axp20x: add support for the AXP318W Precedence: bulk X-Mailing-List: linux-sunxi@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20260910-axp318-regulator-v8-5-e906a61a7f3d@baylibre.com> References: <20260910-axp318-regulator-v8-0-e906a61a7f3d@baylibre.com> In-Reply-To: <20260910-axp318-regulator-v8-0-e906a61a7f3d@baylibre.com> To: Andre Przywara , Lee Jones , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Chen-Yu Tsai , Liam Girdwood , Mark Brown , Hans de Goede Cc: devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, mfd@lists.linux.dev, linux-sunxi@lists.linux.dev, Jerome Brunet X-Mailer: b4 0.16.0 X-Developer-Signature: v=1; a=openpgp-sha256; l=19549; i=jbrunet@baylibre.com; h=from:subject:message-id; bh=mM00w2khOQ1luc9sLRr+7THG50AYVfTw02Km56a/ykA=; b=owEBbQKS/ZANAwAKAeb8Dxw38tqFAcsmYgBqoooa9MAMJ8ZCbXCtk9zZke11ozFa5OPMx9QDa jWdZ+yIBsyJAjMEAAEKAB0WIQT04VmuGPP1bV8btxvm/A8cN/LahQUCaqKKGgAKCRDm/A8cN/La hSnRD/0R5wSQLlb9w3tUVKCKUEq6SrCyoRjzmrp/xX9hqm4tX3HM4tPz60xGFi4vUBPYUuo9iqy DNPQ0WxR6eCDCDm1EcljHW+gO0zveVlJY282jqYRXThIppWooDdXNiUrutitxLCj7i+NaohrUfD 7lEdKn+YYiLG7hKfr1eTBX8w1SoP/Smu0fr4+8Opy9YcjfXHSrHDHa7EKb8NvTHbZRDVaBpmtkP vMZN1fF+uoXXs+RCl2ue/01Ex9u1yIREoY31JPVSsDkkE6Rh2TLY211xNSTyqDPHefOabXrNK16 /6E1ek1726zmQbNBTTO0CL7u9vEwpcA0Kj9vSMSpSIcQDYE7Br5apN3IRvoP48O/auC4K4eaPf9 i0bsnfGNOkzqS7a9dT3IAeXS3cDJTxegNVnOgiMmZ5GyHP5+U97Y/8d0ZUbBrM+dwLt3mwyKLsG kkK1t9xUZO2GbiSLhD8vjMeIwR86wFTv2TJSJVu5oU9/IpS0EYYmHLQoORRc4S/TnB2iqh4mGaC 47T3lfmHLjRDo+YBwci47/79m2vkTZQmbwOelm498F4fLrbBbtsns4kmiwver0sXaNL8vRvoeN1 AtjYNJZCNFKnOuFlmDYwrgxLtPfORFVpJ5ARUqz7oFPKEvCRfs5uJY6sCqlA8hIBa2VClstAs4L 4Ts4G8MaFSOOpZg== X-Developer-Key: i=jbrunet@baylibre.com; a=openpgp; fpr=F29F26CF27BAE1A9719AE6BDC3C92AAF3E60AED9 X-MORS-Enabled: yes X-MORS-DOMAIN: patchwork.local X-MORS-HOSTING: hosting172546 X-MORS-USER: hosting172546 X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= From: Andre Przywara The X-Powers AXP318W is a typical PMIC from X-Powers, featuring nine DC/DC converters and 28 LDOs, on the regulator side. Describe the chip's voltage settings and switch registers, how the voltages are encoded, and connect this to the MFD device via its regulator ID. We use just "318" for the internal identifiers, for easier typing and less churn. If something else other than the "AXP318W" shows up, that's an easy change, externally visible strings carry the additional letter already. Reviewed-by: Chen-Yu Tsai Reviewed-by: Mark Brown Signed-off-by: Andre Przywara Co-developed-by: Jerome Brunet Signed-off-by: Jerome Brunet --- drivers/regulator/axp20x-regulator.c | 319 ++++++++++++++++++++++++++++++++++- 1 file changed, 310 insertions(+), 9 deletions(-) diff --git a/drivers/regulator/axp20x-regulator.c b/drivers/regulator/axp20x-regulator.c index da891415efc0..732541ee619e 100644 --- a/drivers/regulator/axp20x-regulator.c +++ b/drivers/regulator/axp20x-regulator.c @@ -138,6 +138,29 @@ #define AXP313A_DCDC_V_OUT_MASK GENMASK(6, 0) #define AXP313A_LDO_V_OUT_MASK GENMASK(4, 0) +#define AXP318_DCDC1_PFM_PWM_CTRL BIT(7) +#define AXP318_DCDC23_POLYPHASE_CTRL BIT(6) +#define AXP318_DCDC45_POLYPHASE_CTRL BIT(7) +#define AXP318_DCDC1_V_OUT_MASK GENMASK(4, 0) +#define AXP318_DCDC2_V_OUT_MASK GENMASK(6, 0) +#define AXP318_LDO_V_OUT_MASK GENMASK(4, 0) +#define AXP318_ELDO_V_OUT_MASK GENMASK(5, 0) +#define AXP318_THRESHOLD_VOLTAGE 1540000 +/* + * FIXME: + * Some LDOs of the AXP318 may be fed by different supplies and + * the documentation repeatedly warns that output voltage must + * be less than the supply, which is the case for any LDO really. + * + * The best way to let the framework handle this is to set the + * min_dropout_uV field. However the AXP318 documentation + * does not provide any information about this. + * + * Realistically, it can't be less than 1uV so use this + * for all LDOs until we know more. + */ +#define AXP318_LDO_MIN_DROPOUT 1 /* uV */ + #define AXP717_DCDC1_NUM_VOLTAGES 88 #define AXP717_DCDC2_NUM_VOLTAGES 107 #define AXP717_DCDC3_NUM_VOLTAGES 103 @@ -371,8 +394,8 @@ .ops = &axp20x_ops, \ } -#define AXP_DESC(_family, _id, _match, _supply, _min, _max, _step, _vreg, \ - _vmask, _ereg, _emask) \ +#define AXP_DESC_EXT(_family, _id, _match, _supply, _min, _max, _step, _vreg, \ + _vmask, _ereg, _emask, _ops, _bpreg, _bpmask, _dropout) \ [_family##_##_id] = { \ .name = (_match), \ .supply_name = (_supply), \ @@ -384,13 +407,32 @@ .owner = THIS_MODULE, \ .min_uV = (_min) * 1000, \ .uV_step = (_step) * 1000, \ + .min_dropout_uV = (_dropout), \ .vsel_reg = (_vreg), \ .vsel_mask = (_vmask), \ .enable_reg = (_ereg), \ .enable_mask = (_emask), \ - .ops = &axp20x_ops, \ + .bypass_reg = (_bpreg), \ + .bypass_mask = (_bpmask), \ + .ops = (_ops), \ } +#define AXP_DESC(_family, _id, _match, _supply, _min, _max, _step, _vreg, \ + _vmask, _ereg, _emask) \ + AXP_DESC_EXT(_family, _id, _match, _supply, _min, _max, _step, _vreg, \ + _vmask, _ereg, _emask, &axp20x_ops, 0, 0, 0) + +#define AXP_DESC_DO(_family, _id, _match, _supply, _min, _max, _step, _vreg, \ + _vmask, _ereg, _emask, _dropout) \ + AXP_DESC_EXT(_family, _id, _match, _supply, _min, _max, _step, _vreg, \ + _vmask, _ereg, _emask, &axp20x_ops, 0, 0, _dropout) + +#define AXP_DESC_BYPASS(_family, _id, _match, _supply, _min, _max, _step, _vreg,\ + _vmask, _ereg, _emask, _bpreg, _bpmask, _dropout) \ + AXP_DESC_EXT(_family, _id, _match, _supply, _min, _max, _step, _vreg, \ + _vmask, _ereg, _emask, &axp20x_bypass_ops, _bpreg, \ + _bpmask, _dropout) + #define AXP_DESC_SW(_family, _id, _match, _supply, _ereg, _emask) \ [_family##_##_id] = { \ .name = (_match), \ @@ -419,8 +461,9 @@ .ops = &axp20x_ops_fixed \ } -#define AXP_DESC_RANGES_DELAY(_family, _id, _match, _supply, _ranges, _n_voltages, \ - _vreg, _vmask, _ereg, _emask, _ramp_delay) \ +#define AXP_DESC_RANGES_DELAY_OPS(_family, _id, _match, _supply, _ranges, \ + _n_voltages, _vreg, _vmask, _ereg, _emask, \ + _ramp_delay, _ops) \ [_family##_##_id] = { \ .name = (_match), \ .supply_name = (_supply), \ @@ -436,10 +479,23 @@ .enable_mask = (_emask), \ .linear_ranges = (_ranges), \ .n_linear_ranges = ARRAY_SIZE(_ranges), \ - .ramp_delay = (_ramp_delay), \ - .ops = &axp20x_ops_range, \ + .ramp_delay = (_ramp_delay), \ + .ops = (_ops), \ } +#define AXP_DESC_RANGES_THRESHOLD(_family, _id, _match, _supply, _ranges, \ + _n_voltages, _vreg, _vmask, _ereg, _emask) \ + AXP_DESC_RANGES_DELAY_OPS(_family, _id, _match, _supply, _ranges, \ + _n_voltages, _vreg, _vmask, _ereg, _emask, \ + 0, &axp318_threshold_ops_range) + +#define AXP_DESC_RANGES_DELAY(_family, _id, _match, _supply, _ranges, \ + _n_voltages, _vreg, _vmask, _ereg, _emask, \ + _ramp_delay) \ + AXP_DESC_RANGES_DELAY_OPS(_family, _id, _match, _supply, _ranges, \ + _n_voltages, _vreg, _vmask, _ereg, _emask, \ + _ramp_delay, &axp20x_ops_range) + #define AXP_DESC_RANGES(_family, _id, _match, _supply, _ranges, _n_voltages, \ _vreg, _vmask, _ereg, _emask) \ AXP_DESC_RANGES_DELAY(_family, _id, _match, _supply, _ranges, \ @@ -567,6 +623,50 @@ static int axp20x_regulator_enable_regmap(struct regulator_dev *rdev) return regulator_enable_regmap(rdev); }; +static int axp318_threshold_check(struct regulator_dev *rdev, + unsigned int sel) +{ + int old_sel, old_uV, new_uV, enabled; + + /* Only applicable if the regulator is enabled */ + enabled = rdev->desc->ops->is_enabled(rdev); + if (enabled <= 0) + return enabled; + + old_sel = rdev->desc->ops->get_voltage_sel(rdev); + if (old_sel < 0) + return old_sel; + + old_uV = rdev->desc->ops->list_voltage(rdev, old_sel); + if (old_uV < 0) + return old_uV; + + new_uV = rdev->desc->ops->list_voltage(rdev, sel); + if (new_uV < 0) + return new_uV; + + /* Crossing the threshold ? */ + if ((old_uV <= AXP318_THRESHOLD_VOLTAGE && + new_uV > AXP318_THRESHOLD_VOLTAGE) || + (new_uV <= AXP318_THRESHOLD_VOLTAGE && + old_uV > AXP318_THRESHOLD_VOLTAGE)) + return -EBUSY; + + return 0; +} + +static int axp318_threshold_set_voltage_sel(struct regulator_dev *rdev, + unsigned int sel) +{ + int ret; + + ret = axp318_threshold_check(rdev, sel); + if (ret < 0) + return ret; + + return regulator_set_voltage_sel_regmap(rdev, sel); +} + static const struct regulator_ops axp20x_ops_fixed = { .list_voltage = regulator_list_voltage_linear, }; @@ -580,6 +680,15 @@ static const struct regulator_ops axp20x_ops_range = { .is_enabled = regulator_is_enabled_regmap, }; +static const struct regulator_ops axp318_threshold_ops_range = { + .set_voltage_sel = axp318_threshold_set_voltage_sel, + .get_voltage_sel = regulator_get_voltage_sel_regmap, + .list_voltage = regulator_list_voltage_linear_range, + .enable = regulator_enable_regmap, + .disable = regulator_disable_regmap, + .is_enabled = regulator_is_enabled_regmap, +}; + static const struct regulator_ops axp20x_ops = { .set_voltage_sel = regulator_set_voltage_sel_regmap, .get_voltage_sel = regulator_get_voltage_sel_regmap, @@ -590,6 +699,18 @@ static const struct regulator_ops axp20x_ops = { .set_ramp_delay = axp20x_set_ramp_delay, }; +static const struct regulator_ops axp20x_bypass_ops = { + .set_voltage_sel = regulator_set_voltage_sel_regmap, + .get_voltage_sel = regulator_get_voltage_sel_regmap, + .list_voltage = regulator_list_voltage_linear, + .enable = axp20x_regulator_enable_regmap, + .disable = regulator_disable_regmap, + .is_enabled = regulator_is_enabled_regmap, + .set_ramp_delay = axp20x_set_ramp_delay, + .get_bypass = regulator_get_bypass_regmap, + .set_bypass = regulator_set_bypass_regmap, +}; + static const struct regulator_ops axp20x_ops_sw = { .enable = regulator_enable_regmap, .disable = regulator_disable_regmap, @@ -765,6 +886,158 @@ static const struct regulator_desc axp313a_regulators[] = { AXP_DESC_FIXED(AXP313A, RTC_LDO, "rtc-ldo", "vin1", 1800), }; +static const struct linear_range axp318_dcdc2_ranges[] = { + REGULATOR_LINEAR_RANGE(500000, 0, 70, 10000), + REGULATOR_LINEAR_RANGE(1220000, 71, 87, 20000), +}; + +static const struct linear_range axp318_dcdc6_ranges[] = { + REGULATOR_LINEAR_RANGE(500000, 0, 70, 10000), + REGULATOR_LINEAR_RANGE(1220000, 71, 87, 20000), + REGULATOR_LINEAR_RANGE(1800000, 88, 118, 20000), + REGULATOR_LINEAR_RANGE(2440000, 119, 127, 40000), +}; + +static const struct linear_range axp318_dcdc7_ranges[] = { + REGULATOR_LINEAR_RANGE(500000, 0, 70, 10000), + REGULATOR_LINEAR_RANGE(1220000, 71, 102, 20000), +}; + +static const struct linear_range axp318_dcdc8_ranges[] = { + REGULATOR_LINEAR_RANGE(500000, 0, 70, 10000), + REGULATOR_LINEAR_RANGE(1220000, 71, 102, 20000), + REGULATOR_LINEAR_RANGE(1900000, 103, 118, 100000), +}; + +static const struct regulator_desc axp318_regulators[] = { + AXP_DESC(AXP318, DCDC1, "dcdc1", "vin19", 1000, 3400, 100, + AXP318_DCDC1_CONTROL, AXP318_DCDC1_V_OUT_MASK, + AXP318_DCDC_OUTPUT_CONTROL1, BIT(0)), + AXP_DESC_RANGES(AXP318, DCDC2, "dcdc2", "vin23", + axp318_dcdc2_ranges, 88, + AXP318_DCDC2_CONTROL, AXP318_DCDC2_V_OUT_MASK, + AXP318_DCDC_OUTPUT_CONTROL1, BIT(1)), + AXP_DESC_RANGES(AXP318, DCDC3, "dcdc3", "vin23", + axp318_dcdc2_ranges, 88, + AXP318_DCDC3_CONTROL, AXP318_DCDC2_V_OUT_MASK, + AXP318_DCDC_OUTPUT_CONTROL1, BIT(2)), + AXP_DESC_RANGES(AXP318, DCDC4, "dcdc4", "vin45", + axp318_dcdc2_ranges, 88, + AXP318_DCDC4_CONTROL, AXP318_DCDC2_V_OUT_MASK, + AXP318_DCDC_OUTPUT_CONTROL1, BIT(3)), + AXP_DESC_RANGES(AXP318, DCDC5, "dcdc5", "vin45", + axp318_dcdc2_ranges, 88, + AXP318_DCDC5_CONTROL, AXP318_DCDC2_V_OUT_MASK, + AXP318_DCDC_OUTPUT_CONTROL1, BIT(4)), + AXP_DESC_RANGES_THRESHOLD(AXP318, DCDC6, "dcdc6", "vin678", + axp318_dcdc6_ranges, 128, + AXP318_DCDC6_CONTROL, AXP318_DCDC2_V_OUT_MASK, + AXP318_DCDC_OUTPUT_CONTROL1, BIT(5)), + AXP_DESC_RANGES_THRESHOLD(AXP318, DCDC7, "dcdc7", "vin678", + axp318_dcdc7_ranges, 103, + AXP318_DCDC7_CONTROL, AXP318_DCDC2_V_OUT_MASK, + AXP318_DCDC_OUTPUT_CONTROL1, BIT(6)), + AXP_DESC_RANGES_THRESHOLD(AXP318, DCDC8, "dcdc8", "vin678", + axp318_dcdc8_ranges, 119, + AXP318_DCDC8_CONTROL, AXP318_DCDC2_V_OUT_MASK, + AXP318_DCDC_OUTPUT_CONTROL1, BIT(7)), + AXP_DESC_RANGES_THRESHOLD(AXP318, DCDC9, "dcdc9", "vin19", + axp318_dcdc8_ranges, 119, + AXP318_DCDC9_CONTROL, AXP318_DCDC2_V_OUT_MASK, + AXP318_DCDC_OUTPUT_CONTROL2, BIT(0)), + AXP_DESC_SW(AXP318, SWOUT1, "swout1", NULL, + AXP318_DCDC_OUTPUT_CONTROL2, BIT(3)), + AXP_DESC_SW(AXP318, SWOUT2, "swout2", NULL, + AXP318_DCDC_OUTPUT_CONTROL2, BIT(4)), + AXP_DESC_DO(AXP318, ALDO1, "aldo1", "aldo156in", 500, 3400, 100, + AXP318_ALDO1_CONTROL, AXP318_LDO_V_OUT_MASK, + AXP318_LDO_OUTPUT_CONTROL1, BIT(0), AXP318_LDO_MIN_DROPOUT), + AXP_DESC_DO(AXP318, ALDO2, "aldo2", "aldo234in", 500, 3400, 100, + AXP318_ALDO2_CONTROL, AXP318_LDO_V_OUT_MASK, + AXP318_LDO_OUTPUT_CONTROL1, BIT(1), AXP318_LDO_MIN_DROPOUT), + AXP_DESC_DO(AXP318, ALDO3, "aldo3", "aldo234in", 500, 3400, 100, + AXP318_ALDO3_CONTROL, AXP318_LDO_V_OUT_MASK, + AXP318_LDO_OUTPUT_CONTROL1, BIT(2), AXP318_LDO_MIN_DROPOUT), + AXP_DESC_DO(AXP318, ALDO4, "aldo4", "aldo234in", 500, 3400, 100, + AXP318_ALDO4_CONTROL, AXP318_LDO_V_OUT_MASK, + AXP318_LDO_OUTPUT_CONTROL1, BIT(3), AXP318_LDO_MIN_DROPOUT), + AXP_DESC_DO(AXP318, ALDO5, "aldo5", "aldo156in", 500, 3400, 100, + AXP318_ALDO5_CONTROL, AXP318_LDO_V_OUT_MASK, + AXP318_LDO_OUTPUT_CONTROL1, BIT(4), AXP318_LDO_MIN_DROPOUT), + AXP_DESC_DO(AXP318, ALDO6, "aldo6", "aldo156in", 500, 3400, 100, + AXP318_ALDO6_CONTROL, AXP318_LDO_V_OUT_MASK, + AXP318_LDO_OUTPUT_CONTROL1, BIT(5), AXP318_LDO_MIN_DROPOUT), + AXP_DESC_DO(AXP318, BLDO1, "bldo1", "bldoin", 500, 3400, 100, + AXP318_BLDO1_CONTROL, AXP318_LDO_V_OUT_MASK, + AXP318_LDO_OUTPUT_CONTROL1, BIT(6), AXP318_LDO_MIN_DROPOUT), + AXP_DESC_DO(AXP318, BLDO2, "bldo2", "bldoin", 500, 3400, 100, + AXP318_BLDO2_CONTROL, AXP318_LDO_V_OUT_MASK, + AXP318_LDO_OUTPUT_CONTROL1, BIT(7), AXP318_LDO_MIN_DROPOUT), + AXP_DESC_DO(AXP318, BLDO3, "bldo3", "bldoin", 500, 3400, 100, + AXP318_BLDO3_CONTROL, AXP318_LDO_V_OUT_MASK, + AXP318_LDO_OUTPUT_CONTROL2, BIT(0), AXP318_LDO_MIN_DROPOUT), + AXP_DESC_DO(AXP318, BLDO4, "bldo4", "bldoin", 500, 3400, 100, + AXP318_BLDO4_CONTROL, AXP318_LDO_V_OUT_MASK, + AXP318_LDO_OUTPUT_CONTROL2, BIT(1), AXP318_LDO_MIN_DROPOUT), + AXP_DESC_DO(AXP318, BLDO5, "bldo5", "bldoin", 500, 3400, 100, + AXP318_BLDO5_CONTROL, AXP318_LDO_V_OUT_MASK, + AXP318_LDO_OUTPUT_CONTROL2, BIT(2), AXP318_LDO_MIN_DROPOUT), + AXP_DESC_DO(AXP318, CLDO1, "cldo1", "cldoin", 500, 3400, 100, + AXP318_CLDO1_CONTROL, AXP318_LDO_V_OUT_MASK, + AXP318_LDO_OUTPUT_CONTROL2, BIT(3), AXP318_LDO_MIN_DROPOUT), + AXP_DESC_DO(AXP318, CLDO2, "cldo2", "cldoin", 500, 3400, 100, + AXP318_CLDO2_CONTROL, AXP318_LDO_V_OUT_MASK, + AXP318_LDO_OUTPUT_CONTROL2, BIT(4), AXP318_LDO_MIN_DROPOUT), + AXP_DESC_DO(AXP318, CLDO3, "cldo3", "cldoin", 500, 3400, 100, + AXP318_CLDO3_CONTROL, AXP318_LDO_V_OUT_MASK, + AXP318_LDO_OUTPUT_CONTROL2, BIT(5), AXP318_LDO_MIN_DROPOUT), + AXP_DESC_DO(AXP318, CLDO4, "cldo4", "cldoin", 500, 3400, 100, + AXP318_CLDO4_CONTROL, AXP318_LDO_V_OUT_MASK, + AXP318_LDO_OUTPUT_CONTROL2, BIT(6), AXP318_LDO_MIN_DROPOUT), + AXP_DESC_DO(AXP318, CLDO5, "cldo5", "cldoin", 500, 3400, 100, + AXP318_CLDO5_CONTROL, AXP318_LDO_V_OUT_MASK, + AXP318_LDO_OUTPUT_CONTROL2, BIT(7), AXP318_LDO_MIN_DROPOUT), + AXP_DESC_DO(AXP318, DLDO1, "dldo1", "dldoin", 500, 3400, 100, + AXP318_DLDO1_CONTROL, AXP318_LDO_V_OUT_MASK, + AXP318_LDO_OUTPUT_CONTROL3, BIT(0), AXP318_LDO_MIN_DROPOUT), + AXP_DESC_DO(AXP318, DLDO2, "dldo2", "dldoin", 500, 3400, 100, + AXP318_DLDO2_CONTROL, AXP318_LDO_V_OUT_MASK, + AXP318_LDO_OUTPUT_CONTROL3, BIT(1), AXP318_LDO_MIN_DROPOUT), + AXP_DESC_DO(AXP318, DLDO3, "dldo3", "dldoin", 500, 3400, 100, + AXP318_DLDO3_CONTROL, AXP318_LDO_V_OUT_MASK, + AXP318_LDO_OUTPUT_CONTROL3, BIT(2), AXP318_LDO_MIN_DROPOUT), + AXP_DESC_DO(AXP318, DLDO4, "dldo4", "dldoin", 500, 3400, 100, + AXP318_DLDO4_CONTROL, AXP318_LDO_V_OUT_MASK, + AXP318_LDO_OUTPUT_CONTROL3, BIT(3), AXP318_LDO_MIN_DROPOUT), + AXP_DESC_DO(AXP318, DLDO5, "dldo5", "dldoin", 500, 3400, 100, + AXP318_DLDO5_CONTROL, AXP318_LDO_V_OUT_MASK, + AXP318_LDO_OUTPUT_CONTROL3, BIT(4), AXP318_LDO_MIN_DROPOUT), + AXP_DESC_DO(AXP318, DLDO6, "dldo6", "dldoin", 500, 3400, 100, + AXP318_DLDO6_CONTROL, AXP318_LDO_V_OUT_MASK, + AXP318_LDO_OUTPUT_CONTROL3, BIT(5), AXP318_LDO_MIN_DROPOUT), + AXP_DESC_DO(AXP318, ELDO1, "eldo1", "eldoin", 500, 1500, 25, + AXP318_ELDO1_CONTROL, AXP318_ELDO_V_OUT_MASK, + AXP318_LDO_OUTPUT_CONTROL3, BIT(6), AXP318_LDO_MIN_DROPOUT), + AXP_DESC_DO(AXP318, ELDO2, "eldo2", "eldoin", 500, 1500, 25, + AXP318_ELDO2_CONTROL, AXP318_ELDO_V_OUT_MASK, + AXP318_LDO_OUTPUT_CONTROL3, BIT(7), AXP318_LDO_MIN_DROPOUT), + AXP_DESC_DO(AXP318, ELDO3, "eldo3", "eldoin", 500, 1500, 25, + AXP318_ELDO3_CONTROL, AXP318_ELDO_V_OUT_MASK, + AXP318_LDO_OUTPUT_CONTROL4, BIT(0), AXP318_LDO_MIN_DROPOUT), + AXP_DESC_BYPASS(AXP318, ELDO4, "eldo4", "eldoin", 500, 1500, 25, + AXP318_ELDO4_CONTROL, AXP318_ELDO_V_OUT_MASK, + AXP318_LDO_OUTPUT_CONTROL4, BIT(1), + AXP318_ELDO4_CONTROL, BIT(6), AXP318_LDO_MIN_DROPOUT), + AXP_DESC_BYPASS(AXP318, ELDO5, "eldo5", "eldoin", 500, 1500, 25, + AXP318_ELDO5_CONTROL, AXP318_ELDO_V_OUT_MASK, + AXP318_LDO_OUTPUT_CONTROL4, BIT(2), + AXP318_ELDO5_CONTROL, BIT(6), AXP318_LDO_MIN_DROPOUT), + AXP_DESC_DO(AXP318, ELDO6, "eldo6", "eldoin", 500, 1500, 25, + AXP318_ELDO6_CONTROL, AXP318_ELDO_V_OUT_MASK, + AXP318_LDO_OUTPUT_CONTROL4, BIT(3), AXP318_LDO_MIN_DROPOUT), + AXP_DESC_FIXED(AXP318, RTC_LDO, "rtc-ldo", "ips", 1800), +}; + static const struct linear_range axp717_dcdc1_ranges[] = { REGULATOR_LINEAR_RANGE(500000, 0, 70, 10000), REGULATOR_LINEAR_RANGE(1220000, 71, 87, 20000), @@ -1347,6 +1620,7 @@ static int axp20x_set_dcdc_freq(struct platform_device *pdev, u32 dcdcfreq) step = 150; break; case AXP313A_ID: + case AXP318_ID: case AXP323_ID: case AXP717_ID: case AXP15060_ID: @@ -1430,6 +1704,15 @@ static int axp20x_set_dcdc_workmode(struct regulator_dev *rdev, int id, u32 work workmode <<= ffs(mask) - 1; break; + case AXP318_ID: + /* Only DCDC1 has PWM control on the AXP318 */ + if (id != AXP318_DCDC1) + return -EINVAL; + reg = AXP318_DCDC1_CONTROL; + mask = AXP318_DCDC1_PFM_PWM_CTRL; + workmode <<= ffs(mask) - 1; + break; + case AXP806_ID: /* * AXP806 DCDC regulator IDs have the same range as AXP22X. @@ -1543,6 +1826,17 @@ static bool axp20x_is_polyphase_slave(struct axp20x_dev *axp20x, int id) } break; + case AXP318_ID: + regmap_read(axp20x->regmap, AXP318_DCDC_MODE_CTRL1, ®); + + switch (id) { + case AXP318_DCDC3: + return !!(reg & AXP318_DCDC23_POLYPHASE_CTRL); + case AXP318_DCDC5: + return !!(reg & AXP318_DCDC45_POLYPHASE_CTRL); + } + break; + default: return false; } @@ -1585,6 +1879,10 @@ static int axp20x_regulator_probe(struct platform_device *pdev) regulators = axp313a_regulators; nregulators = AXP313A_REG_ID_MAX; break; + case AXP318_ID: + regulators = axp318_regulators; + nregulators = AXP318_REG_ID_MAX; + break; case AXP717_ID: regulators = axp717_regulators; nregulators = AXP717_REG_ID_MAX; @@ -1651,7 +1949,9 @@ static int axp20x_regulator_probe(struct platform_device *pdev) if ((regulators == axp22x_regulators && i == AXP22X_DC1SW) || (regulators == axp803_regulators && i == AXP803_DC1SW) || (regulators == axp809_regulators && i == AXP809_DC1SW) || - (regulators == axp15060_regulators && i == AXP15060_SW)) { + (regulators == axp15060_regulators && i == AXP15060_SW) || + (regulators == axp318_regulators && i == AXP318_SWOUT1) || + (regulators == axp318_regulators && i == AXP318_SWOUT2)) { new_desc = devm_kzalloc(&pdev->dev, sizeof(*desc), GFP_KERNEL); if (!new_desc) @@ -1709,7 +2009,8 @@ static int axp20x_regulator_probe(struct platform_device *pdev) */ if ((regulators == axp22x_regulators && i == AXP22X_DCDC1) || (regulators == axp809_regulators && i == AXP809_DCDC1) || - (regulators == axp15060_regulators && i == AXP15060_DCDC1)) + (regulators == axp15060_regulators && i == AXP15060_DCDC1) || + (regulators == axp318_regulators && i == AXP318_DCDC1)) of_property_read_string(rdev->dev.of_node, "regulator-name", &dcdc1_name);