···2121compatible:2222 "mediatek,mt6323" for PMIC MT63232323 "mediatek,mt6358" for PMIC MT63582424+ "mediatek,mt6359" for PMIC MT63592425 "mediatek,mt6397" for PMIC MT639725262627Optional subnodes:
···117117 description: Enable over current protection.118118 type: boolean119119120120+ regulator-oc-protection-microamp:121121+ description: Set over current protection limit. This is a limit where122122+ hardware performs emergency shutdown. Zero can be passed to disable123123+ protection and value '1' indicates that protection should be enabled but124124+ limit setting can be omitted.125125+126126+ regulator-oc-error-microamp:127127+ description: Set over current error limit. This is a limit where part of128128+ the hardware propably is malfunctional and damage prevention is requested.129129+ Zero can be passed to disable error detection and value '1' indicates130130+ that detection should be enabled but limit setting can be omitted.131131+132132+ regulator-oc-warn-microamp:133133+ description: Set over current warning limit. This is a limit where hardware134134+ is assumed still to be functional but approaching limit where it gets135135+ damaged. Recovery actions should be initiated. Zero can be passed to136136+ disable detection and value '1' indicates that detection should137137+ be enabled but limit setting can be omitted.138138+139139+ regulator-ov-protection-microvolt:140140+ description: Set over voltage protection limit. This is a limit where141141+ hardware performs emergency shutdown. Zero can be passed to disable142142+ protection and value '1' indicates that protection should be enabled but143143+ limit setting can be omitted. Limit is given as microvolt offset from144144+ voltage set to regulator.145145+146146+ regulator-ov-error-microvolt:147147+ description: Set over voltage error limit. This is a limit where part of148148+ the hardware propably is malfunctional and damage prevention is requested149149+ Zero can be passed to disable error detection and value '1' indicates150150+ that detection should be enabled but limit setting can be omitted. Limit151151+ is given as microvolt offset from voltage set to regulator.152152+153153+ regulator-ov-warn-microvolt:154154+ description: Set over voltage warning limit. This is a limit where hardware155155+ is assumed still to be functional but approaching limit where it gets156156+ damaged. Recovery actions should be initiated. Zero can be passed to157157+ disable detection and value '1' indicates that detection should158158+ be enabled but limit setting can be omitted. Limit is given as microvolt159159+ offset from voltage set to regulator.160160+161161+ regulator-uv-protection-microvolt:162162+ description: Set over under voltage protection limit. This is a limit where163163+ hardware performs emergency shutdown. Zero can be passed to disable164164+ protection and value '1' indicates that protection should be enabled but165165+ limit setting can be omitted. Limit is given as microvolt offset from166166+ voltage set to regulator.167167+168168+ regulator-uv-error-microvolt:169169+ description: Set under voltage error limit. This is a limit where part of170170+ the hardware propably is malfunctional and damage prevention is requested171171+ Zero can be passed to disable error detection and value '1' indicates172172+ that detection should be enabled but limit setting can be omitted. Limit173173+ is given as microvolt offset from voltage set to regulator.174174+175175+ regulator-uv-warn-microvolt:176176+ description: Set over under voltage warning limit. This is a limit where177177+ hardware is assumed still to be functional but approaching limit where178178+ it gets damaged. Recovery actions should be initiated. Zero can be passed179179+ to disable detection and value '1' indicates that detection should180180+ be enabled but limit setting can be omitted. Limit is given as microvolt181181+ offset from voltage set to regulator.182182+183183+ regulator-temp-protection-kelvin:184184+ description: Set over temperature protection limit. This is a limit where185185+ hardware performs emergency shutdown. Zero can be passed to disable186186+ protection and value '1' indicates that protection should be enabled but187187+ limit setting can be omitted.188188+189189+ regulator-temp-error-kelvin:190190+ description: Set over temperature error limit. This is a limit where part of191191+ the hardware propably is malfunctional and damage prevention is requested192192+ Zero can be passed to disable error detection and value '1' indicates193193+ that detection should be enabled but limit setting can be omitted.194194+195195+ regulator-temp-warn-kelvin:196196+ description: Set over temperature warning limit. This is a limit where197197+ hardware is assumed still to be functional but approaching limit where it198198+ gets damaged. Recovery actions should be initiated. Zero can be passed to199199+ disable detection and value '1' indicates that detection should200200+ be enabled but limit setting can be omitted.201201+120202 regulator-active-discharge:121203 description: |122204 tristate, enable/disable active discharge of regulators. The values are:
···11+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause22+%YAML 1.233+---44+$id: http://devicetree.org/schemas/regulator/richtek,rt6160-regulator.yaml#55+$schema: http://devicetree.org/meta-schemas/core.yaml#66+77+title: Richtek RT6160 BuckBoost converter88+99+maintainers:1010+ - ChiYuan Huang <cy_huang@richtek.com>1111+1212+description: |1313+ The RT6160 is a high-efficiency buck-boost converter that can provide1414+ up to 3A output current from 2025mV to 5200mV. And it support the wide1515+ input voltage range from 2200mV to 5500mV.1616+1717+ Datasheet is available at1818+ https://www.richtek.com/assets/product_file/RT6160A/DS6160A-00.pdf1919+2020+allOf:2121+ - $ref: regulator.yaml#2222+2323+properties:2424+ compatible:2525+ enum:2626+ - richtek,rt61602727+2828+ reg:2929+ maxItems: 13030+3131+ enable-gpios:3232+ description: A connection of the 'enable' gpio line.3333+ maxItems: 13434+3535+ richtek,vsel-active-low:3636+ description: |3737+ Used to indicate the 'vsel' pin active level. if not specified, use3838+ high active level as the default.3939+ type: boolean4040+4141+required:4242+ - compatible4343+ - reg4444+4545+unevaluatedProperties: false4646+4747+examples:4848+ - |4949+ i2c {5050+ #address-cells = <1>;5151+ #size-cells = <0>;5252+5353+ rt6160@75 {5454+ compatible = "richtek,rt6160";5555+ reg = <0x75>;5656+ enable-gpios = <&gpio26 2 0>;5757+ regulator-name = "rt6160-buckboost";5858+ regulator-min-microvolt = <2025000>;5959+ regulator-max-microvolt = <5200000>;6060+ };6161+ };
···11+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause22+%YAML 1.233+---44+$id: http://devicetree.org/schemas/regulator/richtek,rt6245-regulator.yaml#55+$schema: http://devicetree.org/meta-schemas/core.yaml#66+77+title: Richtek RT6245 High Current Voltage Regulator88+99+maintainers:1010+ - ChiYuan Huang <cy_huang@richtek.com>1111+1212+description: |1313+ The RT6245 is a high-performance, synchronous step-down converter1414+ that can deliver up to 14A output current with an input supply1515+ voltage range of 4.5V to 17V.1616+1717+allOf:1818+ - $ref: regulator.yaml#1919+2020+properties:2121+ compatible:2222+ enum:2323+ - richtek,rt62452424+2525+ reg:2626+ maxItems: 12727+2828+ enable-gpios:2929+ description: |3030+ A connection of the chip 'enable' gpio line. If not provided,3131+ it will be treat as a default-on power.3232+ maxItems: 13333+3434+ richtek,oc-level-select:3535+ $ref: "/schemas/types.yaml#/definitions/uint8"3636+ enum: [0, 1, 2, 3]3737+ description: |3838+ Over current level selection. Each respective value means the current3939+ limit 8A, 14A, 12A, 10A. If this property is missing then keep in4040+ in chip default.4141+4242+ richtek,ot-level-select:4343+ $ref: "/schemas/types.yaml#/definitions/uint8"4444+ enum: [0, 1, 2]4545+ description: |4646+ Over temperature level selection. Each respective value means the degree4747+ 150'c, 130'c, 170'c. If this property is missing then keep in chip4848+ default.4949+5050+ richtek,pgdly-time-select:5151+ $ref: "/schemas/types.yaml#/definitions/uint8"5252+ enum: [0, 1, 2, 3]5353+ description: |5454+ Power good signal delay time selection. Each respective value means the5555+ delay time 0us, 10us, 20us, 40us. If this property is missing then keep5656+ in chip default.5757+5858+5959+ richtek,switch-freq-select:6060+ $ref: "/schemas/types.yaml#/definitions/uint8"6161+ enum: [0, 1, 2]6262+ description: |6363+ Buck switch frequency selection. Each respective value means 400KHz,6464+ 800KHz, 1200KHz. If this property is missing then keep in chip default.6565+6666+required:6767+ - compatible6868+ - reg6969+7070+unevaluatedProperties: false7171+7272+examples:7373+ - |7474+ i2c {7575+ #address-cells = <1>;7676+ #size-cells = <0>;7777+7878+ rt6245@34 {7979+ compatible = "richtek,rt6245";8080+ status = "okay";8181+ reg = <0x34>;8282+ enable-gpios = <&gpio26 2 0>;8383+8484+ regulator-name = "rt6245-regulator";8585+ regulator-min-microvolt = <437500>;8686+ regulator-max-microvolt = <1387500>;8787+ regulator-boot-on;8888+ };8989+ };
···2727 Properties for single regulator.2828 $ref: "regulator.yaml#"29293030+ properties:3131+ rohm,ocw-fet-ron-micro-ohms:3232+ description: |3333+ External FET's ON-resistance. Required if VoutS1 OCP/OCW is3434+ to be set.3535+3036 required:3137 - regulator-name3238
+9-15
Documentation/driver-api/thermal/sysfs-api.rst
···7407405. thermal_emergency_poweroff741741=============================742742743743-On an event of critical trip temperature crossing. Thermal framework744744-allows the system to shutdown gracefully by calling orderly_poweroff().745745-In the event of a failure of orderly_poweroff() to shut down the system746746-we are in danger of keeping the system alive at undesirably high747747-temperatures. To mitigate this high risk scenario we program a work748748-queue to fire after a pre-determined number of seconds to start749749-an emergency shutdown of the device using the kernel_power_off()750750-function. In case kernel_power_off() fails then finally751751-emergency_restart() is called in the worst case.743743+On an event of critical trip temperature crossing the thermal framework744744+shuts down the system by calling hw_protection_shutdown(). The745745+hw_protection_shutdown() first attempts to perform an orderly shutdown746746+but accepts a delay after which it proceeds doing a forced power-off747747+or as last resort an emergency_restart.752748753749The delay should be carefully profiled so as to give adequate time for754754-orderly_poweroff(). In case of failure of an orderly_poweroff() the755755-emergency poweroff kicks in after the delay has elapsed and shuts down756756-the system.750750+orderly poweroff.757751758758-If set to 0 emergency poweroff will not be supported. So a carefully759759-profiled non-zero positive value is a must for emergency poweroff to be760760-triggered.752752+If the delay is set to 0 emergency poweroff will not be supported. So a753753+carefully profiled non-zero positive value is a must for emergency754754+poweroff to be triggered.
+4
MAINTAINERS
···1957819578F: include/linux/regulator/1957919579K: regulator_get_optional19580195801958119581+VOLTAGE AND CURRENT REGULATOR IRQ HELPERS1958219582+R: Matti Vaittinen <matti.vaittinen@fi.rohmeurope.com>1958319583+F: drivers/regulator/irq_helpers.c1958419584+1958119585VRF1958219586M: David Ahern <dsahern@kernel.org>1958319587L: netdev@vger.kernel.org
+62-27
drivers/mfd/mt6358-irq.c
···55#include <linux/interrupt.h>66#include <linux/mfd/mt6358/core.h>77#include <linux/mfd/mt6358/registers.h>88+#include <linux/mfd/mt6359/core.h>99+#include <linux/mfd/mt6359/registers.h>810#include <linux/mfd/mt6397/core.h>911#include <linux/module.h>1012#include <linux/of.h>···1513#include <linux/platform_device.h>1614#include <linux/regmap.h>17151818-static struct irq_top_t mt6358_ints[] = {1616+#define MTK_PMIC_REG_WIDTH 161717+1818+static const struct irq_top_t mt6358_ints[] = {1919 MT6358_TOP_GEN(BUCK),2020 MT6358_TOP_GEN(LDO),2121 MT6358_TOP_GEN(PSC),···2622 MT6358_TOP_GEN(HK),2723 MT6358_TOP_GEN(AUD),2824 MT6358_TOP_GEN(MISC),2525+};2626+2727+static const struct irq_top_t mt6359_ints[] = {2828+ MT6359_TOP_GEN(BUCK),2929+ MT6359_TOP_GEN(LDO),3030+ MT6359_TOP_GEN(PSC),3131+ MT6359_TOP_GEN(SCK),3232+ MT6359_TOP_GEN(BM),3333+ MT6359_TOP_GEN(HK),3434+ MT6359_TOP_GEN(AUD),3535+ MT6359_TOP_GEN(MISC),3636+};3737+3838+static struct pmic_irq_data mt6358_irqd = {3939+ .num_top = ARRAY_SIZE(mt6358_ints),4040+ .num_pmic_irqs = MT6358_IRQ_NR,4141+ .top_int_status_reg = MT6358_TOP_INT_STATUS0,4242+ .pmic_ints = mt6358_ints,4343+};4444+4545+static struct pmic_irq_data mt6359_irqd = {4646+ .num_top = ARRAY_SIZE(mt6359_ints),4747+ .num_pmic_irqs = MT6359_IRQ_NR,4848+ .top_int_status_reg = MT6359_TOP_INT_STATUS0,4949+ .pmic_ints = mt6359_ints,2950};30513152static void pmic_irq_enable(struct irq_data *data)···9162 /* Find out the IRQ group */9263 top_gp = 0;9364 while ((top_gp + 1) < irqd->num_top &&9494- i >= mt6358_ints[top_gp + 1].hwirq_base)6565+ i >= irqd->pmic_ints[top_gp + 1].hwirq_base)9566 top_gp++;96679768 /* Find the IRQ registers */9898- gp_offset = i - mt6358_ints[top_gp].hwirq_base;9999- int_regs = gp_offset / MT6358_REG_WIDTH;100100- shift = gp_offset % MT6358_REG_WIDTH;101101- en_reg = mt6358_ints[top_gp].en_reg +102102- (mt6358_ints[top_gp].en_reg_shift * int_regs);6969+ gp_offset = i - irqd->pmic_ints[top_gp].hwirq_base;7070+ int_regs = gp_offset / MTK_PMIC_REG_WIDTH;7171+ shift = gp_offset % MTK_PMIC_REG_WIDTH;7272+ en_reg = irqd->pmic_ints[top_gp].en_reg +7373+ (irqd->pmic_ints[top_gp].en_reg_shift * int_regs);1037410475 regmap_update_bits(chip->regmap, en_reg, BIT(shift),10576 irqd->enable_hwirq[i] << shift);···12495 unsigned int irq_status, sta_reg, status;12596 unsigned int hwirq, virq;12697 int i, j, ret;9898+ struct pmic_irq_data *irqd = chip->irq_data;12799128128- for (i = 0; i < mt6358_ints[top_gp].num_int_regs; i++) {129129- sta_reg = mt6358_ints[top_gp].sta_reg +130130- mt6358_ints[top_gp].sta_reg_shift * i;100100+ for (i = 0; i < irqd->pmic_ints[top_gp].num_int_regs; i++) {101101+ sta_reg = irqd->pmic_ints[top_gp].sta_reg +102102+ irqd->pmic_ints[top_gp].sta_reg_shift * i;131103132104 ret = regmap_read(chip->regmap, sta_reg, &irq_status);133105 if (ret) {···144114 do {145115 j = __ffs(status);146116147147- hwirq = mt6358_ints[top_gp].hwirq_base +148148- MT6358_REG_WIDTH * i + j;117117+ hwirq = irqd->pmic_ints[top_gp].hwirq_base +118118+ MTK_PMIC_REG_WIDTH * i + j;149119150120 virq = irq_find_mapping(chip->irq_domain, hwirq);151121 if (virq)···161131static irqreturn_t mt6358_irq_handler(int irq, void *data)162132{163133 struct mt6397_chip *chip = data;164164- struct pmic_irq_data *mt6358_irq_data = chip->irq_data;134134+ struct pmic_irq_data *irqd = chip->irq_data;165135 unsigned int bit, i, top_irq_status = 0;166136 int ret;167137168138 ret = regmap_read(chip->regmap,169169- mt6358_irq_data->top_int_status_reg,139139+ irqd->top_int_status_reg,170140 &top_irq_status);171141 if (ret) {172142 dev_err(chip->dev,···174144 return IRQ_NONE;175145 }176146177177- for (i = 0; i < mt6358_irq_data->num_top; i++) {178178- bit = BIT(mt6358_ints[i].top_offset);147147+ for (i = 0; i < irqd->num_top; i++) {148148+ bit = BIT(irqd->pmic_ints[i].top_offset);179149 if (top_irq_status & bit) {180150 mt6358_irq_sp_handler(chip, i);181151 top_irq_status &= ~bit;···210180 int i, j, ret;211181 struct pmic_irq_data *irqd;212182213213- irqd = devm_kzalloc(chip->dev, sizeof(*irqd), GFP_KERNEL);214214- if (!irqd)215215- return -ENOMEM;183183+ switch (chip->chip_id) {184184+ case MT6358_CHIP_ID:185185+ chip->irq_data = &mt6358_irqd;186186+ break;216187217217- chip->irq_data = irqd;188188+ case MT6359_CHIP_ID:189189+ chip->irq_data = &mt6359_irqd;190190+ break;191191+192192+ default:193193+ dev_err(chip->dev, "unsupported chip: 0x%x\n", chip->chip_id);194194+ return -ENODEV;195195+ }218196219197 mutex_init(&chip->irqlock);220220- irqd->top_int_status_reg = MT6358_TOP_INT_STATUS0;221221- irqd->num_pmic_irqs = MT6358_IRQ_NR;222222- irqd->num_top = ARRAY_SIZE(mt6358_ints);223223-198198+ irqd = chip->irq_data;224199 irqd->enable_hwirq = devm_kcalloc(chip->dev,225200 irqd->num_pmic_irqs,226201 sizeof(*irqd->enable_hwirq),···242207243208 /* Disable all interrupts for initializing */244209 for (i = 0; i < irqd->num_top; i++) {245245- for (j = 0; j < mt6358_ints[i].num_int_regs; j++)210210+ for (j = 0; j < irqd->pmic_ints[i].num_int_regs; j++)246211 regmap_write(chip->regmap,247247- mt6358_ints[i].en_reg +248248- mt6358_ints[i].en_reg_shift * j, 0);212212+ irqd->pmic_ints[i].en_reg +213213+ irqd->pmic_ints[i].en_reg_shift * j, 0);249214 }250215251216 chip->irq_domain = irq_domain_add_linear(chip->dev->of_node,
···193193 BCM590xx PMUs. This will enable support for the software194194 controllable LDO/Switching regulators.195195196196-config REGULATOR_BD70528197197- tristate "ROHM BD70528 Power Regulator"198198- depends on MFD_ROHM_BD70528199199- help200200- This driver supports voltage regulators on ROHM BD70528 PMIC.201201- This will enable support for the software controllable buck202202- and LDO regulators.203203-204204- This driver can also be built as a module. If so, the module205205- will be called bd70528-regulator.206206-207196config REGULATOR_BD71815208197 tristate "ROHM BD71815 Power Regulator"209198 depends on MFD_ROHM_BD71828199199+ select REGULATOR_ROHM210200 help211201 This driver supports voltage regulators on ROHM BD71815 PMIC.212202 This will enable support for the software controllable buck···578588 This driver controls a Maxim 8660/8661 voltage output579589 regulator via I2C bus.580590591591+config REGULATOR_MAX8893592592+ tristate "Maxim 8893 voltage regulator"593593+ depends on I2C594594+ select REGMAP_I2C595595+ help596596+ This driver controls a Maxim 8893 voltage output597597+ regulator via I2C bus.598598+581599config REGULATOR_MAX8907582600 tristate "Maxim 8907 voltage regulator"583601 depends on MFD_MAX8907 || COMPILE_TEST···774776 help775777 Say y here to select this option to enable the power regulator of776778 MediaTek MT6358 PMIC.779779+ This driver supports the control of different power rails of device780780+ through regulator interface.781781+782782+config REGULATOR_MT6359783783+ tristate "MediaTek MT6359 PMIC"784784+ depends on MFD_MT6397785785+ help786786+ Say y here to select this option to enable the power regulator of787787+ MediaTek MT6359 PMIC.777788 This driver supports the control of different power rails of device778789 through regulator interface.779790···10371030 RT5033 PMIC. The device supports multiple regulators like10381031 current source, LDO and Buck.1039103210331033+config REGULATOR_RT616010341034+ tristate "Richtek RT6160 BuckBoost voltage regulator"10351035+ depends on I2C10361036+ select REGMAP_I2C10371037+ help10381038+ This adds support for voltage regulator in Richtek RT6160.10391039+ This device automatically change voltage output mode from10401040+ Buck or Boost. The mode transistion depend on the input source voltage.10411041+ The wide output range is from 2025mV to 5200mV and can be used on most10421042+ common application scenario.10431043+10441044+config REGULATOR_RT624510451045+ tristate "Richtek RT6245 voltage regulator"10461046+ depends on I2C10471047+ select REGMAP_I2C10481048+ help10491049+ This adds supprot for Richtek RT6245 voltage regulator.10501050+ It can support up to 14A output current and adjustable output voltage10511051+ from 0.4375V to 1.3875V, per step 12.5mV.10521052+10401053config REGULATOR_RTMV2010411054 tristate "Richtek RTMV20 Laser Diode Regulator"10421055 depends on I2C···11761149 help11771150 This driver supports the internal VMMC regulator in the STw481x11781151 PMIC chips.11521152+11531153+config REGULATOR_SY7636A11541154+ tristate "Silergy SY7636A voltage regulator"11551155+ depends on MFD_SY7636A11561156+ help11571157+ This driver supports Silergy SY3686A voltage regulator.1179115811801159config REGULATOR_SY8106A11811160 tristate "Silergy SY8106A regulator"
···1313#include <linux/init.h>1414#include <linux/err.h>1515#include <linux/platform_device.h>1616+#include <linux/of.h>1717+#include <linux/gpio/consumer.h>1618#include <linux/regulator/driver.h>1719#include <linux/delay.h>1820#include <linux/slab.h>···2624struct bd71815_regulator {2725 struct regulator_desc desc;2826 const struct rohm_dvs_config *dvs;2929-};3030-3131-struct bd71815_pmic {3232- struct bd71815_regulator descs[BD71815_REGULATOR_CNT];3333- struct regmap *regmap;3434- struct device *dev;3535- struct gpio_descs *gps;3636- struct regulator_dev *rdev[BD71815_REGULATOR_CNT];3727};38283929static const int bd7181x_wled_currents[] = {···294300295301static int bd7181x_buck12_get_voltage_sel(struct regulator_dev *rdev)296302{297297- struct bd71815_pmic *pmic = rdev_get_drvdata(rdev);298303 int rid = rdev_get_id(rdev);299304 int ret, regh, regl, val;300305301306 regh = BD71815_REG_BUCK1_VOLT_H + rid * 0x2;302307 regl = BD71815_REG_BUCK1_VOLT_L + rid * 0x2;303308304304- ret = regmap_read(pmic->regmap, regh, &val);309309+ ret = regmap_read(rdev->regmap, regh, &val);305310 if (ret)306311 return ret;307312···312319 * by BD71815_BUCK_DVSSEL bit313320 */314321 if ((!(val & BD71815_BUCK_STBY_DVS)) && (!(val & BD71815_BUCK_DVSSEL)))315315- ret = regmap_read(pmic->regmap, regl, &val);322322+ ret = regmap_read(rdev->regmap, regl, &val);316323317324 if (ret)318325 return ret;···326333static int bd7181x_buck12_set_voltage_sel(struct regulator_dev *rdev,327334 unsigned int sel)328335{329329- struct bd71815_pmic *pmic = rdev_get_drvdata(rdev);330336 int rid = rdev_get_id(rdev);331337 int ret, val, reg, regh, regl;332338333339 regh = BD71815_REG_BUCK1_VOLT_H + rid*0x2;334340 regl = BD71815_REG_BUCK1_VOLT_L + rid*0x2;335341336336- ret = regmap_read(pmic->regmap, regh, &val);342342+ ret = regmap_read(rdev->regmap, regh, &val);337343 if (ret)338344 return ret;339345···342350 * voltages at runtime is not supported by this driver.343351 */344352 if (((val & BD71815_BUCK_STBY_DVS))) {345345- return regmap_update_bits(pmic->regmap, regh, BD71815_VOLT_MASK,353353+ return regmap_update_bits(rdev->regmap, regh, BD71815_VOLT_MASK,346354 sel);347355 }348356 /* Update new voltage to the register which is not selected now */···351359 else352360 reg = regh;353361354354- ret = regmap_update_bits(pmic->regmap, reg, BD71815_VOLT_MASK, sel);362362+ ret = regmap_update_bits(rdev->regmap, reg, BD71815_VOLT_MASK, sel);355363 if (ret)356364 return ret;357365358366 /* Select the other DVS register to be used */359359- return regmap_update_bits(pmic->regmap, regh, BD71815_BUCK_DVSSEL, ~val);367367+ return regmap_update_bits(rdev->regmap, regh, BD71815_BUCK_DVSSEL,368368+ ~val);360369}361370362371static const struct regulator_ops bd7181x_ldo_regulator_ops = {···515522 .dvs = (_dvs), \516523 }517524518518-static struct bd71815_regulator bd71815_regulators[] = {525525+static const struct bd71815_regulator bd71815_regulators[] = {519526 BD71815_BUCK12_REG(buck1, BD71815_BUCK1, BD71815_REG_BUCK1_VOLT_H,520527 BD71815_REG_BUCK1_MODE, 800000, 2000000, 25000,521528 &buck1_dvs),···561568562569static int bd7181x_probe(struct platform_device *pdev)563570{564564- struct bd71815_pmic *pmic;565571 struct regulator_config config = {};566572 int i, ret;567573 struct gpio_desc *ldo4_en;574574+ struct regmap *regmap;568575569569- pmic = devm_kzalloc(&pdev->dev, sizeof(*pmic), GFP_KERNEL);570570- if (!pmic)571571- return -ENOMEM;572572-573573- memcpy(pmic->descs, bd71815_regulators, sizeof(pmic->descs));574574-575575- pmic->dev = &pdev->dev;576576- pmic->regmap = dev_get_regmap(pdev->dev.parent, NULL);577577- if (!pmic->regmap) {578578- dev_err(pmic->dev, "No parent regmap\n");576576+ regmap = dev_get_regmap(pdev->dev.parent, NULL);577577+ if (!regmap) {578578+ dev_err(&pdev->dev, "No parent regmap\n");579579 return -ENODEV;580580 }581581- platform_set_drvdata(pdev, pmic);582581 ldo4_en = devm_gpiod_get_from_of_node(&pdev->dev,583582 pdev->dev.parent->of_node,584583 "rohm,vsel-gpios", 0,···584599 }585600586601 /* Disable to go to ship-mode */587587- ret = regmap_update_bits(pmic->regmap, BD71815_REG_PWRCTRL,588588- RESTARTEN, 0);602602+ ret = regmap_update_bits(regmap, BD71815_REG_PWRCTRL, RESTARTEN, 0);589603 if (ret)590604 return ret;591605592606 config.dev = pdev->dev.parent;593593- config.regmap = pmic->regmap;607607+ config.regmap = regmap;594608595609 for (i = 0; i < BD71815_REGULATOR_CNT; i++) {596596- struct regulator_desc *desc;610610+ const struct regulator_desc *desc;597611 struct regulator_dev *rdev;598612599599- desc = &pmic->descs[i].desc;613613+ desc = &bd71815_regulators[i].desc;614614+600615 if (i == BD71815_LDO4)601616 config.ena_gpiod = ldo4_en;602602-603603- config.driver_data = pmic;617617+ else618618+ config.ena_gpiod = NULL;604619605620 rdev = devm_regulator_register(&pdev->dev, desc, &config);606621 if (IS_ERR(rdev)) {···609624 desc->name);610625 return PTR_ERR(rdev);611626 }612612- config.ena_gpiod = NULL;613613- pmic->rdev[i] = rdev;614627 }615628 return 0;616629}···622639static struct platform_driver bd7181x_regulator = {623640 .driver = {624641 .name = "bd7181x-pmic",625625- .owner = THIS_MODULE,626642 },627643 .probe = bd7181x_probe,628644 .id_table = bd7181x_pmic_id,
+948-140
drivers/regulator/bd9576-regulator.c
···22// Copyright (C) 2020 ROHM Semiconductors33// ROHM BD9576MUF/BD9573MUF regulator driver4455-#include <linux/delay.h>65#include <linux/err.h>76#include <linux/gpio/consumer.h>87#include <linux/interrupt.h>88+#include <linux/jiffies.h>99#include <linux/kernel.h>1010#include <linux/mfd/rohm-bd957x.h>1111#include <linux/mfd/rohm-generic.h>···1616#include <linux/regulator/machine.h>1717#include <linux/regulator/of_regulator.h>1818#include <linux/slab.h>1919+#include <linux/spinlock.h>2020+#include <linux/workqueue.h>19212022#define BD957X_VOUTS1_VOLT 33000002123#define BD957X_VOUTS4_BASE_VOLT 10300002224#define BD957X_VOUTS34_NUM_VOLT 3223252424-static int vout1_volt_table[] = {5000000, 4900000, 4800000, 4700000, 4600000,2525- 4500000, 4500000, 4500000, 5000000, 5100000,2626- 5200000, 5300000, 5400000, 5500000, 5500000,2727- 5500000};2626+#define BD9576_THERM_IRQ_MASK_TW BIT(5)2727+#define BD9576_xVD_IRQ_MASK_VOUTL1 BIT(5)2828+#define BD9576_UVD_IRQ_MASK_VOUTS1_OCW BIT(6)2929+#define BD9576_xVD_IRQ_MASK_VOUT1TO4 0x0F28302929-static int vout2_volt_table[] = {1800000, 1780000, 1760000, 1740000, 1720000,3030- 1700000, 1680000, 1660000, 1800000, 1820000,3131- 1840000, 1860000, 1880000, 1900000, 1920000,3232- 1940000};3131+static const unsigned int vout1_volt_table[] = {3232+ 5000000, 4900000, 4800000, 4700000, 4600000,3333+ 4500000, 4500000, 4500000, 5000000, 5100000,3434+ 5200000, 5300000, 5400000, 5500000, 5500000,3535+ 55000003636+};33373434-static int voutl1_volt_table[] = {2500000, 2540000, 2580000, 2620000, 2660000,3535- 2700000, 2740000, 2780000, 2500000, 2460000,3636- 2420000, 2380000, 2340000, 2300000, 2260000,3737- 2220000};3838+static const unsigned int vout2_volt_table[] = {3939+ 1800000, 1780000, 1760000, 1740000, 1720000,4040+ 1700000, 1680000, 1660000, 1800000, 1820000,4141+ 1840000, 1860000, 1880000, 1900000, 1920000,4242+ 19400004343+};4444+4545+static const unsigned int voutl1_volt_table[] = {4646+ 2500000, 2540000, 2580000, 2620000, 2660000,4747+ 2700000, 2740000, 2780000, 2500000, 2460000,4848+ 2420000, 2380000, 2340000, 2300000, 2260000,4949+ 22200005050+};5151+5252+static const struct linear_range vout1_xvd_ranges[] = {5353+ REGULATOR_LINEAR_RANGE(225000, 0x01, 0x2b, 0),5454+ REGULATOR_LINEAR_RANGE(225000, 0x2c, 0x54, 5000),5555+ REGULATOR_LINEAR_RANGE(425000, 0x55, 0x7f, 0),5656+};5757+5858+static const struct linear_range vout234_xvd_ranges[] = {5959+ REGULATOR_LINEAR_RANGE(17000, 0x01, 0x0f, 0),6060+ REGULATOR_LINEAR_RANGE(17000, 0x10, 0x6d, 1000),6161+ REGULATOR_LINEAR_RANGE(110000, 0x6e, 0x7f, 0),6262+};6363+6464+static const struct linear_range voutL1_xvd_ranges[] = {6565+ REGULATOR_LINEAR_RANGE(34000, 0x01, 0x0f, 0),6666+ REGULATOR_LINEAR_RANGE(34000, 0x10, 0x6d, 2000),6767+ REGULATOR_LINEAR_RANGE(220000, 0x6e, 0x7f, 0),6868+};6969+7070+static struct linear_range voutS1_ocw_ranges_internal[] = {7171+ REGULATOR_LINEAR_RANGE(200000, 0x01, 0x04, 0),7272+ REGULATOR_LINEAR_RANGE(250000, 0x05, 0x18, 50000),7373+ REGULATOR_LINEAR_RANGE(1200000, 0x19, 0x3f, 0),7474+};7575+7676+static struct linear_range voutS1_ocw_ranges[] = {7777+ REGULATOR_LINEAR_RANGE(50000, 0x01, 0x04, 0),7878+ REGULATOR_LINEAR_RANGE(60000, 0x05, 0x18, 10000),7979+ REGULATOR_LINEAR_RANGE(250000, 0x19, 0x3f, 0),8080+};8181+8282+static struct linear_range voutS1_ocp_ranges_internal[] = {8383+ REGULATOR_LINEAR_RANGE(300000, 0x01, 0x06, 0),8484+ REGULATOR_LINEAR_RANGE(350000, 0x7, 0x1b, 50000),8585+ REGULATOR_LINEAR_RANGE(1350000, 0x1c, 0x3f, 0),8686+};8787+8888+static struct linear_range voutS1_ocp_ranges[] = {8989+ REGULATOR_LINEAR_RANGE(70000, 0x01, 0x06, 0),9090+ REGULATOR_LINEAR_RANGE(80000, 0x7, 0x1b, 10000),9191+ REGULATOR_LINEAR_RANGE(280000, 0x1c, 0x3f, 0),9292+};38933994struct bd957x_regulator_data {4095 struct regulator_desc desc;4196 int base_voltage;9797+ struct regulator_dev *rdev;9898+ int ovd_notif;9999+ int uvd_notif;100100+ int temp_notif;101101+ int ovd_err;102102+ int uvd_err;103103+ int temp_err;104104+ const struct linear_range *xvd_ranges;105105+ int num_xvd_ranges;106106+ bool oc_supported;107107+ unsigned int ovd_reg;108108+ unsigned int uvd_reg;109109+ unsigned int xvd_mask;110110+ unsigned int ocp_reg;111111+ unsigned int ocp_mask;112112+ unsigned int ocw_reg;113113+ unsigned int ocw_mask;114114+ unsigned int ocw_rfet;115115+};116116+117117+#define BD9576_NUM_REGULATORS 6118118+#define BD9576_NUM_OVD_REGULATORS 5119119+120120+struct bd957x_data {121121+ struct bd957x_regulator_data regulator_data[BD9576_NUM_REGULATORS];122122+ struct regmap *regmap;123123+ struct delayed_work therm_irq_suppress;124124+ struct delayed_work ovd_irq_suppress;125125+ struct delayed_work uvd_irq_suppress;126126+ unsigned int therm_irq;127127+ unsigned int ovd_irq;128128+ unsigned int uvd_irq;129129+ spinlock_t err_lock;130130+ int regulator_global_err;42131};4313244133static int bd957x_vout34_list_voltage(struct regulator_dev *rdev,···16172 return desc->volt_table[index];16273}16374164164-static const struct regulator_ops bd957x_vout34_ops = {7575+static void bd9576_fill_ovd_flags(struct bd957x_regulator_data *data,7676+ bool warn)7777+{7878+ if (warn) {7979+ data->ovd_notif = REGULATOR_EVENT_OVER_VOLTAGE_WARN;8080+ data->ovd_err = REGULATOR_ERROR_OVER_VOLTAGE_WARN;8181+ } else {8282+ data->ovd_notif = REGULATOR_EVENT_REGULATION_OUT;8383+ data->ovd_err = REGULATOR_ERROR_REGULATION_OUT;8484+ }8585+}8686+8787+static void bd9576_fill_ocp_flags(struct bd957x_regulator_data *data,8888+ bool warn)8989+{9090+ if (warn) {9191+ data->uvd_notif = REGULATOR_EVENT_OVER_CURRENT_WARN;9292+ data->uvd_err = REGULATOR_ERROR_OVER_CURRENT_WARN;9393+ } else {9494+ data->uvd_notif = REGULATOR_EVENT_OVER_CURRENT;9595+ data->uvd_err = REGULATOR_ERROR_OVER_CURRENT;9696+ }9797+}9898+9999+static void bd9576_fill_uvd_flags(struct bd957x_regulator_data *data,100100+ bool warn)101101+{102102+ if (warn) {103103+ data->uvd_notif = REGULATOR_EVENT_UNDER_VOLTAGE_WARN;104104+ data->uvd_err = REGULATOR_ERROR_UNDER_VOLTAGE_WARN;105105+ } else {106106+ data->uvd_notif = REGULATOR_EVENT_UNDER_VOLTAGE;107107+ data->uvd_err = REGULATOR_ERROR_UNDER_VOLTAGE;108108+ }109109+}110110+111111+static void bd9576_fill_temp_flags(struct bd957x_regulator_data *data,112112+ bool enable, bool warn)113113+{114114+ if (!enable) {115115+ data->temp_notif = 0;116116+ data->temp_err = 0;117117+ } else if (warn) {118118+ data->temp_notif = REGULATOR_EVENT_OVER_TEMP_WARN;119119+ data->temp_err = REGULATOR_ERROR_OVER_TEMP_WARN;120120+ } else {121121+ data->temp_notif = REGULATOR_EVENT_OVER_TEMP;122122+ data->temp_err = REGULATOR_ERROR_OVER_TEMP;123123+ }124124+}125125+126126+static int bd9576_set_limit(const struct linear_range *r, int num_ranges,127127+ struct regmap *regmap, int reg, int mask, int lim)128128+{129129+ int ret;130130+ bool found;131131+ int sel = 0;132132+133133+ if (lim) {134134+135135+ ret = linear_range_get_selector_low_array(r, num_ranges,136136+ lim, &sel, &found);137137+ if (ret)138138+ return ret;139139+140140+ if (!found)141141+ dev_warn(regmap_get_device(regmap),142142+ "limit %d out of range. Setting lower\n",143143+ lim);144144+ }145145+146146+ return regmap_update_bits(regmap, reg, mask, sel);147147+}148148+149149+static bool check_ocp_flag_mismatch(struct regulator_dev *rdev, int severity,150150+ struct bd957x_regulator_data *r)151151+{152152+ if ((severity == REGULATOR_SEVERITY_ERR &&153153+ r->uvd_notif != REGULATOR_EVENT_OVER_CURRENT) ||154154+ (severity == REGULATOR_SEVERITY_WARN &&155155+ r->uvd_notif != REGULATOR_EVENT_OVER_CURRENT_WARN)) {156156+ dev_warn(rdev_get_dev(rdev),157157+ "Can't support both OCP WARN and ERR\n");158158+ /* Do not overwrite ERR config with WARN */159159+ if (severity == REGULATOR_SEVERITY_WARN)160160+ return true;161161+162162+ bd9576_fill_ocp_flags(r, 0);163163+ }164164+165165+ return false;166166+}167167+168168+static bool check_uvd_flag_mismatch(struct regulator_dev *rdev, int severity,169169+ struct bd957x_regulator_data *r)170170+{171171+ if ((severity == REGULATOR_SEVERITY_ERR &&172172+ r->uvd_notif != REGULATOR_EVENT_UNDER_VOLTAGE) ||173173+ (severity == REGULATOR_SEVERITY_WARN &&174174+ r->uvd_notif != REGULATOR_EVENT_UNDER_VOLTAGE_WARN)) {175175+ dev_warn(rdev_get_dev(rdev),176176+ "Can't support both UVD WARN and ERR\n");177177+ if (severity == REGULATOR_SEVERITY_WARN)178178+ return true;179179+180180+ bd9576_fill_uvd_flags(r, 0);181181+ }182182+183183+ return false;184184+}185185+186186+static bool check_ovd_flag_mismatch(struct regulator_dev *rdev, int severity,187187+ struct bd957x_regulator_data *r)188188+{189189+ if ((severity == REGULATOR_SEVERITY_ERR &&190190+ r->ovd_notif != REGULATOR_EVENT_REGULATION_OUT) ||191191+ (severity == REGULATOR_SEVERITY_WARN &&192192+ r->ovd_notif != REGULATOR_EVENT_OVER_VOLTAGE_WARN)) {193193+ dev_warn(rdev_get_dev(rdev),194194+ "Can't support both OVD WARN and ERR\n");195195+ if (severity == REGULATOR_SEVERITY_WARN)196196+ return true;197197+198198+ bd9576_fill_ovd_flags(r, 0);199199+ }200200+201201+ return false;202202+}203203+204204+static bool check_temp_flag_mismatch(struct regulator_dev *rdev, int severity,205205+ struct bd957x_regulator_data *r)206206+{207207+ if ((severity == REGULATOR_SEVERITY_ERR &&208208+ r->ovd_notif != REGULATOR_EVENT_OVER_TEMP) ||209209+ (severity == REGULATOR_SEVERITY_WARN &&210210+ r->ovd_notif != REGULATOR_EVENT_OVER_TEMP_WARN)) {211211+ dev_warn(rdev_get_dev(rdev),212212+ "Can't support both thermal WARN and ERR\n");213213+ if (severity == REGULATOR_SEVERITY_WARN)214214+ return true;215215+ }216216+217217+ return false;218218+}219219+220220+static int bd9576_set_ocp(struct regulator_dev *rdev, int lim_uA, int severity,221221+ bool enable)222222+{223223+ struct bd957x_data *d;224224+ struct bd957x_regulator_data *r;225225+ int reg, mask;226226+ int Vfet, rfet;227227+ const struct linear_range *range;228228+ int num_ranges;229229+230230+ if ((lim_uA && !enable) || (!lim_uA && enable))231231+ return -EINVAL;232232+233233+ r = container_of(rdev->desc, struct bd957x_regulator_data, desc);234234+ if (!r->oc_supported)235235+ return -EINVAL;236236+237237+ d = rdev_get_drvdata(rdev);238238+239239+ if (severity == REGULATOR_SEVERITY_PROT) {240240+ reg = r->ocp_reg;241241+ mask = r->ocp_mask;242242+ if (r->ocw_rfet) {243243+ range = voutS1_ocp_ranges;244244+ num_ranges = ARRAY_SIZE(voutS1_ocp_ranges);245245+ rfet = r->ocw_rfet / 1000;246246+ } else {247247+ range = voutS1_ocp_ranges_internal;248248+ num_ranges = ARRAY_SIZE(voutS1_ocp_ranges_internal);249249+ /* Internal values are already micro-amperes */250250+ rfet = 1000;251251+ }252252+ } else {253253+ reg = r->ocw_reg;254254+ mask = r->ocw_mask;255255+256256+ if (r->ocw_rfet) {257257+ range = voutS1_ocw_ranges;258258+ num_ranges = ARRAY_SIZE(voutS1_ocw_ranges);259259+ rfet = r->ocw_rfet / 1000;260260+ } else {261261+ range = voutS1_ocw_ranges_internal;262262+ num_ranges = ARRAY_SIZE(voutS1_ocw_ranges_internal);263263+ /* Internal values are already micro-amperes */264264+ rfet = 1000;265265+ }266266+267267+ /* We abuse uvd fields for OCW on VoutS1 */268268+ if (r->uvd_notif) {269269+ /*270270+ * If both warning and error are requested, prioritize271271+ * ERROR configuration272272+ */273273+ if (check_ocp_flag_mismatch(rdev, severity, r))274274+ return 0;275275+ } else {276276+ bool warn = severity == REGULATOR_SEVERITY_WARN;277277+278278+ bd9576_fill_ocp_flags(r, warn);279279+ }280280+ }281281+282282+ /*283283+ * limits are given in uA, rfet is mOhm284284+ * Divide lim_uA by 1000 to get Vfet in uV.285285+ * (We expect both Rfet and limit uA to be magnitude of hundreds of286286+ * milli Amperes & milli Ohms => we should still have decent accuracy)287287+ */288288+ Vfet = lim_uA/1000 * rfet;289289+290290+ return bd9576_set_limit(range, num_ranges, d->regmap,291291+ reg, mask, Vfet);292292+}293293+294294+static int bd9576_set_uvp(struct regulator_dev *rdev, int lim_uV, int severity,295295+ bool enable)296296+{297297+ struct bd957x_data *d;298298+ struct bd957x_regulator_data *r;299299+ int mask, reg;300300+301301+ if (severity == REGULATOR_SEVERITY_PROT) {302302+ if (!enable || lim_uV)303303+ return -EINVAL;304304+ return 0;305305+ }306306+307307+ /*308308+ * BD9576 has enable control as a special value in limit reg. Can't309309+ * set limit but keep feature disabled or enable W/O given limit.310310+ */311311+ if ((lim_uV && !enable) || (!lim_uV && enable))312312+ return -EINVAL;313313+314314+ r = container_of(rdev->desc, struct bd957x_regulator_data, desc);315315+ d = rdev_get_drvdata(rdev);316316+317317+ mask = r->xvd_mask;318318+ reg = r->uvd_reg;319319+ /*320320+ * Check that there is no mismatch for what the detection IRQs are to321321+ * be used.322322+ */323323+ if (r->uvd_notif) {324324+ if (check_uvd_flag_mismatch(rdev, severity, r))325325+ return 0;326326+ } else {327327+ bd9576_fill_uvd_flags(r, severity == REGULATOR_SEVERITY_WARN);328328+ }329329+330330+ return bd9576_set_limit(r->xvd_ranges, r->num_xvd_ranges, d->regmap,331331+ reg, mask, lim_uV);332332+}333333+334334+static int bd9576_set_ovp(struct regulator_dev *rdev, int lim_uV, int severity,335335+ bool enable)336336+{337337+ struct bd957x_data *d;338338+ struct bd957x_regulator_data *r;339339+ int mask, reg;340340+341341+ if (severity == REGULATOR_SEVERITY_PROT) {342342+ if (!enable || lim_uV)343343+ return -EINVAL;344344+ return 0;345345+ }346346+347347+ /*348348+ * BD9576 has enable control as a special value in limit reg. Can't349349+ * set limit but keep feature disabled or enable W/O given limit.350350+ */351351+ if ((lim_uV && !enable) || (!lim_uV && enable))352352+ return -EINVAL;353353+354354+ r = container_of(rdev->desc, struct bd957x_regulator_data, desc);355355+ d = rdev_get_drvdata(rdev);356356+357357+ mask = r->xvd_mask;358358+ reg = r->ovd_reg;359359+ /*360360+ * Check that there is no mismatch for what the detection IRQs are to361361+ * be used.362362+ */363363+ if (r->ovd_notif) {364364+ if (check_ovd_flag_mismatch(rdev, severity, r))365365+ return 0;366366+ } else {367367+ bd9576_fill_ovd_flags(r, severity == REGULATOR_SEVERITY_WARN);368368+ }369369+370370+ return bd9576_set_limit(r->xvd_ranges, r->num_xvd_ranges, d->regmap,371371+ reg, mask, lim_uV);372372+}373373+374374+375375+static int bd9576_set_tw(struct regulator_dev *rdev, int lim, int severity,376376+ bool enable)377377+{378378+ struct bd957x_data *d;379379+ struct bd957x_regulator_data *r;380380+ int i;381381+382382+ /*383383+ * BD9576MUF has fixed temperature limits384384+ * The detection can only be enabled/disabled385385+ */386386+ if (lim)387387+ return -EINVAL;388388+389389+ /* Protection can't be disabled */390390+ if (severity == REGULATOR_SEVERITY_PROT) {391391+ if (!enable)392392+ return -EINVAL;393393+ else394394+ return 0;395395+ }396396+397397+ r = container_of(rdev->desc, struct bd957x_regulator_data, desc);398398+ d = rdev_get_drvdata(rdev);399399+400400+ /*401401+ * Check that there is no mismatch for what the detection IRQs are to402402+ * be used.403403+ */404404+ if (r->temp_notif)405405+ if (check_temp_flag_mismatch(rdev, severity, r))406406+ return 0;407407+408408+ bd9576_fill_temp_flags(r, enable, severity == REGULATOR_SEVERITY_WARN);409409+410410+ if (enable)411411+ return regmap_update_bits(d->regmap, BD957X_REG_INT_THERM_MASK,412412+ BD9576_THERM_IRQ_MASK_TW, 0);413413+414414+ /*415415+ * If any of the regulators is interested in thermal warning we keep IRQ416416+ * enabled.417417+ */418418+ for (i = 0; i < BD9576_NUM_REGULATORS; i++)419419+ if (d->regulator_data[i].temp_notif)420420+ return 0;421421+422422+ return regmap_update_bits(d->regmap, BD957X_REG_INT_THERM_MASK,423423+ BD9576_THERM_IRQ_MASK_TW,424424+ BD9576_THERM_IRQ_MASK_TW);425425+}426426+427427+static const struct regulator_ops bd9573_vout34_ops = {165428 .is_enabled = regulator_is_enabled_regmap,166429 .list_voltage = bd957x_vout34_list_voltage,167430 .get_voltage_sel = regulator_get_voltage_sel_regmap,168431};169432170170-static const struct regulator_ops bd957X_vouts1_regulator_ops = {433433+static const struct regulator_ops bd9576_vout34_ops = {434434+ .is_enabled = regulator_is_enabled_regmap,435435+ .list_voltage = bd957x_vout34_list_voltage,436436+ .get_voltage_sel = regulator_get_voltage_sel_regmap,437437+ .set_over_voltage_protection = bd9576_set_ovp,438438+ .set_under_voltage_protection = bd9576_set_uvp,439439+ .set_thermal_protection = bd9576_set_tw,440440+};441441+442442+static const struct regulator_ops bd9573_vouts1_regulator_ops = {171443 .is_enabled = regulator_is_enabled_regmap,172444};173445174174-static const struct regulator_ops bd957x_ops = {446446+static const struct regulator_ops bd9576_vouts1_regulator_ops = {447447+ .is_enabled = regulator_is_enabled_regmap,448448+ .set_over_current_protection = bd9576_set_ocp,449449+};450450+451451+static const struct regulator_ops bd9573_ops = {175452 .is_enabled = regulator_is_enabled_regmap,176453 .list_voltage = bd957x_list_voltage,177454 .get_voltage_sel = regulator_get_voltage_sel_regmap,178455};179456180180-static struct bd957x_regulator_data bd9576_regulators[] = {181181- {182182- .desc = {183183- .name = "VD50",184184- .of_match = of_match_ptr("regulator-vd50"),185185- .regulators_node = of_match_ptr("regulators"),186186- .id = BD957X_VD50,187187- .type = REGULATOR_VOLTAGE,188188- .ops = &bd957x_ops,189189- .volt_table = &vout1_volt_table[0],190190- .n_voltages = ARRAY_SIZE(vout1_volt_table),191191- .vsel_reg = BD957X_REG_VOUT1_TUNE,192192- .vsel_mask = BD957X_MASK_VOUT1_TUNE,193193- .enable_reg = BD957X_REG_POW_TRIGGER1,194194- .enable_mask = BD957X_REGULATOR_EN_MASK,195195- .enable_val = BD957X_REGULATOR_DIS_VAL,196196- .enable_is_inverted = true,197197- .owner = THIS_MODULE,457457+static const struct regulator_ops bd9576_ops = {458458+ .is_enabled = regulator_is_enabled_regmap,459459+ .list_voltage = bd957x_list_voltage,460460+ .get_voltage_sel = regulator_get_voltage_sel_regmap,461461+ .set_over_voltage_protection = bd9576_set_ovp,462462+ .set_under_voltage_protection = bd9576_set_uvp,463463+ .set_thermal_protection = bd9576_set_tw,464464+};465465+466466+static const struct regulator_ops *bd9573_ops_arr[] = {467467+ [BD957X_VD50] = &bd9573_ops,468468+ [BD957X_VD18] = &bd9573_ops,469469+ [BD957X_VDDDR] = &bd9573_vout34_ops,470470+ [BD957X_VD10] = &bd9573_vout34_ops,471471+ [BD957X_VOUTL1] = &bd9573_ops,472472+ [BD957X_VOUTS1] = &bd9573_vouts1_regulator_ops,473473+};474474+475475+static const struct regulator_ops *bd9576_ops_arr[] = {476476+ [BD957X_VD50] = &bd9576_ops,477477+ [BD957X_VD18] = &bd9576_ops,478478+ [BD957X_VDDDR] = &bd9576_vout34_ops,479479+ [BD957X_VD10] = &bd9576_vout34_ops,480480+ [BD957X_VOUTL1] = &bd9576_ops,481481+ [BD957X_VOUTS1] = &bd9576_vouts1_regulator_ops,482482+};483483+484484+static int vouts1_get_fet_res(struct device_node *np,485485+ const struct regulator_desc *desc,486486+ struct regulator_config *cfg)487487+{488488+ struct bd957x_regulator_data *data;489489+ int ret;490490+ u32 uohms;491491+492492+ data = container_of(desc, struct bd957x_regulator_data, desc);493493+494494+ ret = of_property_read_u32(np, "rohm,ocw-fet-ron-micro-ohms", &uohms);495495+ if (ret) {496496+ if (ret != -EINVAL)497497+ return ret;498498+499499+ return 0;500500+ }501501+ data->ocw_rfet = uohms;502502+ return 0;503503+}504504+505505+static struct bd957x_data bd957x_regulators = {506506+ .regulator_data = {507507+ {508508+ .desc = {509509+ .name = "VD50",510510+ .of_match = of_match_ptr("regulator-vd50"),511511+ .regulators_node = of_match_ptr("regulators"),512512+ .id = BD957X_VD50,513513+ .type = REGULATOR_VOLTAGE,514514+ .volt_table = &vout1_volt_table[0],515515+ .n_voltages = ARRAY_SIZE(vout1_volt_table),516516+ .vsel_reg = BD957X_REG_VOUT1_TUNE,517517+ .vsel_mask = BD957X_MASK_VOUT1_TUNE,518518+ .enable_reg = BD957X_REG_POW_TRIGGER1,519519+ .enable_mask = BD957X_REGULATOR_EN_MASK,520520+ .enable_val = BD957X_REGULATOR_DIS_VAL,521521+ .enable_is_inverted = true,522522+ .owner = THIS_MODULE,523523+ },524524+ .xvd_ranges = vout1_xvd_ranges,525525+ .num_xvd_ranges = ARRAY_SIZE(vout1_xvd_ranges),526526+ .ovd_reg = BD9576_REG_VOUT1_OVD,527527+ .uvd_reg = BD9576_REG_VOUT1_UVD,528528+ .xvd_mask = BD9576_MASK_XVD,198529 },199199- },200200- {201201- .desc = {202202- .name = "VD18",203203- .of_match = of_match_ptr("regulator-vd18"),204204- .regulators_node = of_match_ptr("regulators"),205205- .id = BD957X_VD18,206206- .type = REGULATOR_VOLTAGE,207207- .ops = &bd957x_ops,208208- .volt_table = &vout2_volt_table[0],209209- .n_voltages = ARRAY_SIZE(vout2_volt_table),210210- .vsel_reg = BD957X_REG_VOUT2_TUNE,211211- .vsel_mask = BD957X_MASK_VOUT2_TUNE,212212- .enable_reg = BD957X_REG_POW_TRIGGER2,213213- .enable_mask = BD957X_REGULATOR_EN_MASK,214214- .enable_val = BD957X_REGULATOR_DIS_VAL,215215- .enable_is_inverted = true,216216- .owner = THIS_MODULE,530530+ {531531+ .desc = {532532+ .name = "VD18",533533+ .of_match = of_match_ptr("regulator-vd18"),534534+ .regulators_node = of_match_ptr("regulators"),535535+ .id = BD957X_VD18,536536+ .type = REGULATOR_VOLTAGE,537537+ .volt_table = &vout2_volt_table[0],538538+ .n_voltages = ARRAY_SIZE(vout2_volt_table),539539+ .vsel_reg = BD957X_REG_VOUT2_TUNE,540540+ .vsel_mask = BD957X_MASK_VOUT2_TUNE,541541+ .enable_reg = BD957X_REG_POW_TRIGGER2,542542+ .enable_mask = BD957X_REGULATOR_EN_MASK,543543+ .enable_val = BD957X_REGULATOR_DIS_VAL,544544+ .enable_is_inverted = true,545545+ .owner = THIS_MODULE,546546+ },547547+ .xvd_ranges = vout234_xvd_ranges,548548+ .num_xvd_ranges = ARRAY_SIZE(vout234_xvd_ranges),549549+ .ovd_reg = BD9576_REG_VOUT2_OVD,550550+ .uvd_reg = BD9576_REG_VOUT2_UVD,551551+ .xvd_mask = BD9576_MASK_XVD,217552 },218218- },219219- {220220- .desc = {221221- .name = "VDDDR",222222- .of_match = of_match_ptr("regulator-vdddr"),223223- .regulators_node = of_match_ptr("regulators"),224224- .id = BD957X_VDDDR,225225- .ops = &bd957x_vout34_ops,226226- .type = REGULATOR_VOLTAGE,227227- .n_voltages = BD957X_VOUTS34_NUM_VOLT,228228- .vsel_reg = BD957X_REG_VOUT3_TUNE,229229- .vsel_mask = BD957X_MASK_VOUT3_TUNE,230230- .enable_reg = BD957X_REG_POW_TRIGGER3,231231- .enable_mask = BD957X_REGULATOR_EN_MASK,232232- .enable_val = BD957X_REGULATOR_DIS_VAL,233233- .enable_is_inverted = true,234234- .owner = THIS_MODULE,553553+ {554554+ .desc = {555555+ .name = "VDDDR",556556+ .of_match = of_match_ptr("regulator-vdddr"),557557+ .regulators_node = of_match_ptr("regulators"),558558+ .id = BD957X_VDDDR,559559+ .type = REGULATOR_VOLTAGE,560560+ .n_voltages = BD957X_VOUTS34_NUM_VOLT,561561+ .vsel_reg = BD957X_REG_VOUT3_TUNE,562562+ .vsel_mask = BD957X_MASK_VOUT3_TUNE,563563+ .enable_reg = BD957X_REG_POW_TRIGGER3,564564+ .enable_mask = BD957X_REGULATOR_EN_MASK,565565+ .enable_val = BD957X_REGULATOR_DIS_VAL,566566+ .enable_is_inverted = true,567567+ .owner = THIS_MODULE,568568+ },569569+ .ovd_reg = BD9576_REG_VOUT3_OVD,570570+ .uvd_reg = BD9576_REG_VOUT3_UVD,571571+ .xvd_mask = BD9576_MASK_XVD,572572+ .xvd_ranges = vout234_xvd_ranges,573573+ .num_xvd_ranges = ARRAY_SIZE(vout234_xvd_ranges),235574 },236236- },237237- {238238- .desc = {239239- .name = "VD10",240240- .of_match = of_match_ptr("regulator-vd10"),241241- .regulators_node = of_match_ptr("regulators"),242242- .id = BD957X_VD10,243243- .ops = &bd957x_vout34_ops,244244- .type = REGULATOR_VOLTAGE,245245- .fixed_uV = BD957X_VOUTS4_BASE_VOLT,246246- .n_voltages = BD957X_VOUTS34_NUM_VOLT,247247- .vsel_reg = BD957X_REG_VOUT4_TUNE,248248- .vsel_mask = BD957X_MASK_VOUT4_TUNE,249249- .enable_reg = BD957X_REG_POW_TRIGGER4,250250- .enable_mask = BD957X_REGULATOR_EN_MASK,251251- .enable_val = BD957X_REGULATOR_DIS_VAL,252252- .enable_is_inverted = true,253253- .owner = THIS_MODULE,575575+ {576576+ .desc = {577577+ .name = "VD10",578578+ .of_match = of_match_ptr("regulator-vd10"),579579+ .regulators_node = of_match_ptr("regulators"),580580+ .id = BD957X_VD10,581581+ .type = REGULATOR_VOLTAGE,582582+ .fixed_uV = BD957X_VOUTS4_BASE_VOLT,583583+ .n_voltages = BD957X_VOUTS34_NUM_VOLT,584584+ .vsel_reg = BD957X_REG_VOUT4_TUNE,585585+ .vsel_mask = BD957X_MASK_VOUT4_TUNE,586586+ .enable_reg = BD957X_REG_POW_TRIGGER4,587587+ .enable_mask = BD957X_REGULATOR_EN_MASK,588588+ .enable_val = BD957X_REGULATOR_DIS_VAL,589589+ .enable_is_inverted = true,590590+ .owner = THIS_MODULE,591591+ },592592+ .xvd_ranges = vout234_xvd_ranges,593593+ .num_xvd_ranges = ARRAY_SIZE(vout234_xvd_ranges),594594+ .ovd_reg = BD9576_REG_VOUT4_OVD,595595+ .uvd_reg = BD9576_REG_VOUT4_UVD,596596+ .xvd_mask = BD9576_MASK_XVD,254597 },255255- },256256- {257257- .desc = {258258- .name = "VOUTL1",259259- .of_match = of_match_ptr("regulator-voutl1"),260260- .regulators_node = of_match_ptr("regulators"),261261- .id = BD957X_VOUTL1,262262- .ops = &bd957x_ops,263263- .type = REGULATOR_VOLTAGE,264264- .volt_table = &voutl1_volt_table[0],265265- .n_voltages = ARRAY_SIZE(voutl1_volt_table),266266- .vsel_reg = BD957X_REG_VOUTL1_TUNE,267267- .vsel_mask = BD957X_MASK_VOUTL1_TUNE,268268- .enable_reg = BD957X_REG_POW_TRIGGERL1,269269- .enable_mask = BD957X_REGULATOR_EN_MASK,270270- .enable_val = BD957X_REGULATOR_DIS_VAL,271271- .enable_is_inverted = true,272272- .owner = THIS_MODULE,598598+ {599599+ .desc = {600600+ .name = "VOUTL1",601601+ .of_match = of_match_ptr("regulator-voutl1"),602602+ .regulators_node = of_match_ptr("regulators"),603603+ .id = BD957X_VOUTL1,604604+ .type = REGULATOR_VOLTAGE,605605+ .volt_table = &voutl1_volt_table[0],606606+ .n_voltages = ARRAY_SIZE(voutl1_volt_table),607607+ .vsel_reg = BD957X_REG_VOUTL1_TUNE,608608+ .vsel_mask = BD957X_MASK_VOUTL1_TUNE,609609+ .enable_reg = BD957X_REG_POW_TRIGGERL1,610610+ .enable_mask = BD957X_REGULATOR_EN_MASK,611611+ .enable_val = BD957X_REGULATOR_DIS_VAL,612612+ .enable_is_inverted = true,613613+ .owner = THIS_MODULE,614614+ },615615+ .xvd_ranges = voutL1_xvd_ranges,616616+ .num_xvd_ranges = ARRAY_SIZE(voutL1_xvd_ranges),617617+ .ovd_reg = BD9576_REG_VOUTL1_OVD,618618+ .uvd_reg = BD9576_REG_VOUTL1_UVD,619619+ .xvd_mask = BD9576_MASK_XVD,273620 },274274- },275275- {276276- .desc = {277277- .name = "VOUTS1",278278- .of_match = of_match_ptr("regulator-vouts1"),279279- .regulators_node = of_match_ptr("regulators"),280280- .id = BD957X_VOUTS1,281281- .ops = &bd957X_vouts1_regulator_ops,282282- .type = REGULATOR_VOLTAGE,283283- .n_voltages = 1,284284- .fixed_uV = BD957X_VOUTS1_VOLT,285285- .enable_reg = BD957X_REG_POW_TRIGGERS1,286286- .enable_mask = BD957X_REGULATOR_EN_MASK,287287- .enable_val = BD957X_REGULATOR_DIS_VAL,288288- .enable_is_inverted = true,289289- .owner = THIS_MODULE,621621+ {622622+ .desc = {623623+ .name = "VOUTS1",624624+ .of_match = of_match_ptr("regulator-vouts1"),625625+ .regulators_node = of_match_ptr("regulators"),626626+ .id = BD957X_VOUTS1,627627+ .type = REGULATOR_VOLTAGE,628628+ .n_voltages = 1,629629+ .fixed_uV = BD957X_VOUTS1_VOLT,630630+ .enable_reg = BD957X_REG_POW_TRIGGERS1,631631+ .enable_mask = BD957X_REGULATOR_EN_MASK,632632+ .enable_val = BD957X_REGULATOR_DIS_VAL,633633+ .enable_is_inverted = true,634634+ .owner = THIS_MODULE,635635+ .of_parse_cb = vouts1_get_fet_res,636636+ },637637+ .oc_supported = true,638638+ .ocw_reg = BD9576_REG_VOUT1S_OCW,639639+ .ocw_mask = BD9576_MASK_VOUT1S_OCW,640640+ .ocp_reg = BD9576_REG_VOUT1S_OCP,641641+ .ocp_mask = BD9576_MASK_VOUT1S_OCP,290642 },291643 },292644};293645646646+static int bd9576_renable(struct regulator_irq_data *rid, int reg, int mask)647647+{648648+ int val, ret;649649+ struct bd957x_data *d = (struct bd957x_data *)rid->data;650650+651651+ ret = regmap_read(d->regmap, reg, &val);652652+ if (ret)653653+ return REGULATOR_FAILED_RETRY;654654+655655+ if (rid->opaque && rid->opaque == (val & mask)) {656656+ /*657657+ * It seems we stil have same status. Ack and return658658+ * information that we are still out of limits and core659659+ * should not enable IRQ660660+ */661661+ regmap_write(d->regmap, reg, mask & val);662662+ return REGULATOR_ERROR_ON;663663+ }664664+ rid->opaque = 0;665665+ /*666666+ * Status was changed. Either prolem was solved or we have new issues.667667+ * Let's re-enable IRQs and be prepared to report problems again668668+ */669669+ return REGULATOR_ERROR_CLEARED;670670+}671671+672672+static int bd9576_uvd_renable(struct regulator_irq_data *rid)673673+{674674+ return bd9576_renable(rid, BD957X_REG_INT_UVD_STAT, UVD_IRQ_VALID_MASK);675675+}676676+677677+static int bd9576_ovd_renable(struct regulator_irq_data *rid)678678+{679679+ return bd9576_renable(rid, BD957X_REG_INT_OVD_STAT, OVD_IRQ_VALID_MASK);680680+}681681+682682+static int bd9576_temp_renable(struct regulator_irq_data *rid)683683+{684684+ return bd9576_renable(rid, BD957X_REG_INT_THERM_STAT,685685+ BD9576_THERM_IRQ_MASK_TW);686686+}687687+688688+static int bd9576_uvd_handler(int irq, struct regulator_irq_data *rid,689689+ unsigned long *dev_mask)690690+{691691+ int val, ret, i;692692+ struct bd957x_data *d = (struct bd957x_data *)rid->data;693693+694694+ ret = regmap_read(d->regmap, BD957X_REG_INT_UVD_STAT, &val);695695+ if (ret)696696+ return REGULATOR_FAILED_RETRY;697697+698698+ *dev_mask = 0;699699+700700+ rid->opaque = val & UVD_IRQ_VALID_MASK;701701+702702+ /*703703+ * Go through the set status bits and report either error or warning704704+ * to the notifier depending on what was flagged in DT705705+ */706706+ *dev_mask = val & BD9576_xVD_IRQ_MASK_VOUT1TO4;707707+ /* There is 1 bit gap in register after Vout1 .. Vout4 statuses */708708+ *dev_mask |= ((val & BD9576_xVD_IRQ_MASK_VOUTL1) >> 1);709709+ /*710710+ * We (ab)use the uvd for OCW notification. DT parsing should711711+ * have added correct OCW flag to uvd_notif and uvd_err for S1712712+ */713713+ *dev_mask |= ((val & BD9576_UVD_IRQ_MASK_VOUTS1_OCW) >> 1);714714+715715+ for_each_set_bit(i, dev_mask, 6) {716716+ struct bd957x_regulator_data *rdata;717717+ struct regulator_err_state *stat;718718+719719+ rdata = &d->regulator_data[i];720720+ stat = &rid->states[i];721721+722722+ stat->notifs = rdata->uvd_notif;723723+ stat->errors = rdata->uvd_err;724724+ }725725+726726+ ret = regmap_write(d->regmap, BD957X_REG_INT_UVD_STAT,727727+ UVD_IRQ_VALID_MASK & val);728728+729729+ return 0;730730+}731731+732732+static int bd9576_ovd_handler(int irq, struct regulator_irq_data *rid,733733+ unsigned long *dev_mask)734734+{735735+ int val, ret, i;736736+ struct bd957x_data *d = (struct bd957x_data *)rid->data;737737+738738+ ret = regmap_read(d->regmap, BD957X_REG_INT_OVD_STAT, &val);739739+ if (ret)740740+ return REGULATOR_FAILED_RETRY;741741+742742+ rid->opaque = val & OVD_IRQ_VALID_MASK;743743+ *dev_mask = 0;744744+745745+ if (!(val & OVD_IRQ_VALID_MASK))746746+ return 0;747747+748748+ *dev_mask = val & BD9576_xVD_IRQ_MASK_VOUT1TO4;749749+ /* There is 1 bit gap in register after Vout1 .. Vout4 statuses */750750+ *dev_mask |= ((val & BD9576_xVD_IRQ_MASK_VOUTL1) >> 1);751751+752752+ for_each_set_bit(i, dev_mask, 5) {753753+ struct bd957x_regulator_data *rdata;754754+ struct regulator_err_state *stat;755755+756756+ rdata = &d->regulator_data[i];757757+ stat = &rid->states[i];758758+759759+ stat->notifs = rdata->ovd_notif;760760+ stat->errors = rdata->ovd_err;761761+ }762762+763763+ /* Clear the sub-IRQ status */764764+ regmap_write(d->regmap, BD957X_REG_INT_OVD_STAT,765765+ OVD_IRQ_VALID_MASK & val);766766+767767+ return 0;768768+}769769+770770+#define BD9576_DEV_MASK_ALL_REGULATORS 0x3F771771+772772+static int bd9576_thermal_handler(int irq, struct regulator_irq_data *rid,773773+ unsigned long *dev_mask)774774+{775775+ int val, ret, i;776776+ struct bd957x_data *d = (struct bd957x_data *)rid->data;777777+778778+ ret = regmap_read(d->regmap, BD957X_REG_INT_THERM_STAT, &val);779779+ if (ret)780780+ return REGULATOR_FAILED_RETRY;781781+782782+ if (!(val & BD9576_THERM_IRQ_MASK_TW)) {783783+ *dev_mask = 0;784784+ return 0;785785+ }786786+787787+ *dev_mask = BD9576_DEV_MASK_ALL_REGULATORS;788788+789789+ for (i = 0; i < BD9576_NUM_REGULATORS; i++) {790790+ struct bd957x_regulator_data *rdata;791791+ struct regulator_err_state *stat;792792+793793+ rdata = &d->regulator_data[i];794794+ stat = &rid->states[i];795795+796796+ stat->notifs = rdata->temp_notif;797797+ stat->errors = rdata->temp_err;798798+ }799799+800800+ /* Clear the sub-IRQ status */801801+ regmap_write(d->regmap, BD957X_REG_INT_THERM_STAT,802802+ BD9576_THERM_IRQ_MASK_TW);803803+804804+ return 0;805805+}806806+294807static int bd957x_probe(struct platform_device *pdev)295808{296296- struct regmap *regmap;297297- struct regulator_config config = { 0 };298809 int i;299299- bool vout_mode, ddr_sel;300300- const struct bd957x_regulator_data *reg_data = &bd9576_regulators[0];301301- unsigned int num_reg_data = ARRAY_SIZE(bd9576_regulators);810810+ unsigned int num_reg_data;811811+ bool vout_mode, ddr_sel, may_have_irqs = false;812812+ struct regmap *regmap;813813+ struct bd957x_data *ic_data;814814+ struct regulator_config config = { 0 };815815+ /* All regulators are related to UVD and thermal IRQs... */816816+ struct regulator_dev *rdevs[BD9576_NUM_REGULATORS];817817+ /* ...But VoutS1 is not flagged by OVD IRQ */818818+ struct regulator_dev *ovd_devs[BD9576_NUM_OVD_REGULATORS];819819+ static const struct regulator_irq_desc bd9576_notif_uvd = {820820+ .name = "bd9576-uvd",821821+ .irq_off_ms = 1000,822822+ .map_event = bd9576_uvd_handler,823823+ .renable = bd9576_uvd_renable,824824+ .data = &bd957x_regulators,825825+ };826826+ static const struct regulator_irq_desc bd9576_notif_ovd = {827827+ .name = "bd9576-ovd",828828+ .irq_off_ms = 1000,829829+ .map_event = bd9576_ovd_handler,830830+ .renable = bd9576_ovd_renable,831831+ .data = &bd957x_regulators,832832+ };833833+ static const struct regulator_irq_desc bd9576_notif_temp = {834834+ .name = "bd9576-temp",835835+ .irq_off_ms = 1000,836836+ .map_event = bd9576_thermal_handler,837837+ .renable = bd9576_temp_renable,838838+ .data = &bd957x_regulators,839839+ };302840 enum rohm_chip_type chip = platform_get_device_id(pdev)->driver_data;841841+842842+ num_reg_data = ARRAY_SIZE(bd957x_regulators.regulator_data);843843+844844+ ic_data = &bd957x_regulators;303845304846 regmap = dev_get_regmap(pdev->dev.parent, NULL);305847 if (!regmap) {306848 dev_err(&pdev->dev, "No regmap\n");307849 return -EINVAL;308850 }851851+852852+ ic_data->regmap = regmap;309853 vout_mode = of_property_read_bool(pdev->dev.parent->of_node,310854 "rohm,vout1-en-low");311855 if (vout_mode) {···985263 * bytes and use bd9576_regulators directly for non-constant configs986264 * like DDR voltage selection.987265 */266266+ platform_set_drvdata(pdev, ic_data);988267 ddr_sel = of_property_read_bool(pdev->dev.parent->of_node,989268 "rohm,ddr-sel-low");990269 if (ddr_sel)991991- bd9576_regulators[2].desc.fixed_uV = 1350000;270270+ ic_data->regulator_data[2].desc.fixed_uV = 1350000;992271 else993993- bd9576_regulators[2].desc.fixed_uV = 1500000;272272+ ic_data->regulator_data[2].desc.fixed_uV = 1500000;994273995274 switch (chip) {996275 case ROHM_CHIP_TYPE_BD9576:276276+ may_have_irqs = true;997277 dev_dbg(&pdev->dev, "Found BD9576MUF\n");998278 break;999279 case ROHM_CHIP_TYPE_BD9573:···1006282 return -EINVAL;1007283 }1008284285285+ for (i = 0; i < num_reg_data; i++) {286286+ struct regulator_desc *d;287287+288288+ d = &ic_data->regulator_data[i].desc;289289+290290+291291+ if (may_have_irqs) {292292+ if (d->id >= ARRAY_SIZE(bd9576_ops_arr))293293+ return -EINVAL;294294+295295+ d->ops = bd9576_ops_arr[d->id];296296+ } else {297297+ if (d->id >= ARRAY_SIZE(bd9573_ops_arr))298298+ return -EINVAL;299299+300300+ d->ops = bd9573_ops_arr[d->id];301301+ }302302+ }303303+1009304 config.dev = pdev->dev.parent;1010305 config.regmap = regmap;306306+ config.driver_data = ic_data;10113071012308 for (i = 0; i < num_reg_data; i++) {101330910141014- const struct regulator_desc *desc;10151015- struct regulator_dev *rdev;10161016- const struct bd957x_regulator_data *r;310310+ struct bd957x_regulator_data *r = &ic_data->regulator_data[i];311311+ const struct regulator_desc *desc = &r->desc;101731210181018- r = ®_data[i];10191019- desc = &r->desc;10201020-10211021- rdev = devm_regulator_register(&pdev->dev, desc, &config);10221022- if (IS_ERR(rdev)) {313313+ r->rdev = devm_regulator_register(&pdev->dev, desc,314314+ &config);315315+ if (IS_ERR(r->rdev)) {1023316 dev_err(&pdev->dev,1024317 "failed to register %s regulator\n",1025318 desc->name);10261026- return PTR_ERR(rdev);319319+ return PTR_ERR(r->rdev);1027320 }1028321 /*1029322 * Clear the VOUT1 GPIO setting - rest of the regulators do not1030323 * support GPIO control1031324 */1032325 config.ena_gpiod = NULL;10331033- }1034326327327+ if (!may_have_irqs)328328+ continue;329329+330330+ rdevs[i] = r->rdev;331331+ if (i < BD957X_VOUTS1)332332+ ovd_devs[i] = r->rdev;333333+ }334334+ if (may_have_irqs) {335335+ void *ret;336336+ /*337337+ * We can add both the possible error and warning flags here338338+ * because the core uses these only for status clearing and339339+ * if we use warnings - errors are always clear and the other340340+ * way around. We can also add CURRENT flag for all regulators341341+ * because it is never set if it is not supported. Same applies342342+ * to setting UVD for VoutS1 - it is not accidentally cleared343343+ * as it is never set.344344+ */345345+ int uvd_errs = REGULATOR_ERROR_UNDER_VOLTAGE |346346+ REGULATOR_ERROR_UNDER_VOLTAGE_WARN |347347+ REGULATOR_ERROR_OVER_CURRENT |348348+ REGULATOR_ERROR_OVER_CURRENT_WARN;349349+ int ovd_errs = REGULATOR_ERROR_OVER_VOLTAGE_WARN |350350+ REGULATOR_ERROR_REGULATION_OUT;351351+ int temp_errs = REGULATOR_ERROR_OVER_TEMP |352352+ REGULATOR_ERROR_OVER_TEMP_WARN;353353+ int irq;354354+355355+ irq = platform_get_irq_byname(pdev, "bd9576-uvd");356356+357357+ /* Register notifiers - can fail if IRQ is not given */358358+ ret = devm_regulator_irq_helper(&pdev->dev, &bd9576_notif_uvd,359359+ irq, 0, uvd_errs, NULL,360360+ &rdevs[0],361361+ BD9576_NUM_REGULATORS);362362+ if (IS_ERR(ret)) {363363+ if (PTR_ERR(ret) == -EPROBE_DEFER)364364+ return -EPROBE_DEFER;365365+366366+ dev_warn(&pdev->dev, "UVD disabled %pe\n", ret);367367+ }368368+369369+ irq = platform_get_irq_byname(pdev, "bd9576-ovd");370370+371371+ ret = devm_regulator_irq_helper(&pdev->dev, &bd9576_notif_ovd,372372+ irq, 0, ovd_errs, NULL,373373+ &ovd_devs[0],374374+ BD9576_NUM_OVD_REGULATORS);375375+ if (IS_ERR(ret)) {376376+ if (PTR_ERR(ret) == -EPROBE_DEFER)377377+ return -EPROBE_DEFER;378378+379379+ dev_warn(&pdev->dev, "OVD disabled %pe\n", ret);380380+ }381381+ irq = platform_get_irq_byname(pdev, "bd9576-temp");382382+383383+ ret = devm_regulator_irq_helper(&pdev->dev, &bd9576_notif_temp,384384+ irq, 0, temp_errs, NULL,385385+ &rdevs[0],386386+ BD9576_NUM_REGULATORS);387387+ if (IS_ERR(ret)) {388388+ if (PTR_ERR(ret) == -EPROBE_DEFER)389389+ return -EPROBE_DEFER;390390+391391+ dev_warn(&pdev->dev, "Thermal warning disabled %pe\n",392392+ ret);393393+ }394394+ }1035395 return 0;1036396}10373971038398static const struct platform_device_id bd957x_pmic_id[] = {10391039- { "bd9573-pmic", ROHM_CHIP_TYPE_BD9573 },10401040- { "bd9576-pmic", ROHM_CHIP_TYPE_BD9576 },399399+ { "bd9573-regulator", ROHM_CHIP_TYPE_BD9573 },400400+ { "bd9576-regulator", ROHM_CHIP_TYPE_BD9576 },1041401 { },1042402};1043403MODULE_DEVICE_TABLE(platform, bd957x_pmic_id);
+228-90
drivers/regulator/core.c
···3333#include "dummy.h"3434#include "internal.h"35353636-#define rdev_crit(rdev, fmt, ...) \3737- pr_crit("%s: " fmt, rdev_get_name(rdev), ##__VA_ARGS__)3838-#define rdev_err(rdev, fmt, ...) \3939- pr_err("%s: " fmt, rdev_get_name(rdev), ##__VA_ARGS__)4040-#define rdev_warn(rdev, fmt, ...) \4141- pr_warn("%s: " fmt, rdev_get_name(rdev), ##__VA_ARGS__)4242-#define rdev_info(rdev, fmt, ...) \4343- pr_info("%s: " fmt, rdev_get_name(rdev), ##__VA_ARGS__)4444-#define rdev_dbg(rdev, fmt, ...) \4545- pr_debug("%s: " fmt, rdev_get_name(rdev), ##__VA_ARGS__)4646-4736static DEFINE_WW_CLASS(regulator_ww_class);4837static DEFINE_MUTEX(regulator_nesting_mutex);4938static DEFINE_MUTEX(regulator_list_mutex);···106117 else107118 return "";108119}120120+EXPORT_SYMBOL_GPL(rdev_get_name);109121110122static bool have_full_constraints(void)111123{···581591 return rstate;582592}583593584584-static ssize_t regulator_uV_show(struct device *dev,585585- struct device_attribute *attr, char *buf)594594+static ssize_t microvolts_show(struct device *dev,595595+ struct device_attribute *attr, char *buf)586596{587597 struct regulator_dev *rdev = dev_get_drvdata(dev);588598 int uV;···595605 return uV;596606 return sprintf(buf, "%d\n", uV);597607}598598-static DEVICE_ATTR(microvolts, 0444, regulator_uV_show, NULL);608608+static DEVICE_ATTR_RO(microvolts);599609600600-static ssize_t regulator_uA_show(struct device *dev,601601- struct device_attribute *attr, char *buf)610610+static ssize_t microamps_show(struct device *dev,611611+ struct device_attribute *attr, char *buf)602612{603613 struct regulator_dev *rdev = dev_get_drvdata(dev);604614605615 return sprintf(buf, "%d\n", _regulator_get_current_limit(rdev));606616}607607-static DEVICE_ATTR(microamps, 0444, regulator_uA_show, NULL);617617+static DEVICE_ATTR_RO(microamps);608618609619static ssize_t name_show(struct device *dev, struct device_attribute *attr,610620 char *buf)···635645 return sprintf(buf, "%s\n", regulator_opmode_to_str(mode));636646}637647638638-static ssize_t regulator_opmode_show(struct device *dev,639639- struct device_attribute *attr, char *buf)648648+static ssize_t opmode_show(struct device *dev,649649+ struct device_attribute *attr, char *buf)640650{641651 struct regulator_dev *rdev = dev_get_drvdata(dev);642652643653 return regulator_print_opmode(buf, _regulator_get_mode(rdev));644654}645645-static DEVICE_ATTR(opmode, 0444, regulator_opmode_show, NULL);655655+static DEVICE_ATTR_RO(opmode);646656647657static ssize_t regulator_print_state(char *buf, int state)648658{···654664 return sprintf(buf, "unknown\n");655665}656666657657-static ssize_t regulator_state_show(struct device *dev,658658- struct device_attribute *attr, char *buf)667667+static ssize_t state_show(struct device *dev,668668+ struct device_attribute *attr, char *buf)659669{660670 struct regulator_dev *rdev = dev_get_drvdata(dev);661671 ssize_t ret;···666676667677 return ret;668678}669669-static DEVICE_ATTR(state, 0444, regulator_state_show, NULL);679679+static DEVICE_ATTR_RO(state);670680671671-static ssize_t regulator_status_show(struct device *dev,672672- struct device_attribute *attr, char *buf)681681+static ssize_t status_show(struct device *dev,682682+ struct device_attribute *attr, char *buf)673683{674684 struct regulator_dev *rdev = dev_get_drvdata(dev);675685 int status;···713723714724 return sprintf(buf, "%s\n", label);715725}716716-static DEVICE_ATTR(status, 0444, regulator_status_show, NULL);726726+static DEVICE_ATTR_RO(status);717727718718-static ssize_t regulator_min_uA_show(struct device *dev,719719- struct device_attribute *attr, char *buf)728728+static ssize_t min_microamps_show(struct device *dev,729729+ struct device_attribute *attr, char *buf)720730{721731 struct regulator_dev *rdev = dev_get_drvdata(dev);722732···725735726736 return sprintf(buf, "%d\n", rdev->constraints->min_uA);727737}728728-static DEVICE_ATTR(min_microamps, 0444, regulator_min_uA_show, NULL);738738+static DEVICE_ATTR_RO(min_microamps);729739730730-static ssize_t regulator_max_uA_show(struct device *dev,731731- struct device_attribute *attr, char *buf)740740+static ssize_t max_microamps_show(struct device *dev,741741+ struct device_attribute *attr, char *buf)732742{733743 struct regulator_dev *rdev = dev_get_drvdata(dev);734744···737747738748 return sprintf(buf, "%d\n", rdev->constraints->max_uA);739749}740740-static DEVICE_ATTR(max_microamps, 0444, regulator_max_uA_show, NULL);750750+static DEVICE_ATTR_RO(max_microamps);741751742742-static ssize_t regulator_min_uV_show(struct device *dev,743743- struct device_attribute *attr, char *buf)752752+static ssize_t min_microvolts_show(struct device *dev,753753+ struct device_attribute *attr, char *buf)744754{745755 struct regulator_dev *rdev = dev_get_drvdata(dev);746756···749759750760 return sprintf(buf, "%d\n", rdev->constraints->min_uV);751761}752752-static DEVICE_ATTR(min_microvolts, 0444, regulator_min_uV_show, NULL);762762+static DEVICE_ATTR_RO(min_microvolts);753763754754-static ssize_t regulator_max_uV_show(struct device *dev,755755- struct device_attribute *attr, char *buf)764764+static ssize_t max_microvolts_show(struct device *dev,765765+ struct device_attribute *attr, char *buf)756766{757767 struct regulator_dev *rdev = dev_get_drvdata(dev);758768···761771762772 return sprintf(buf, "%d\n", rdev->constraints->max_uV);763773}764764-static DEVICE_ATTR(max_microvolts, 0444, regulator_max_uV_show, NULL);774774+static DEVICE_ATTR_RO(max_microvolts);765775766766-static ssize_t regulator_total_uA_show(struct device *dev,767767- struct device_attribute *attr, char *buf)776776+static ssize_t requested_microamps_show(struct device *dev,777777+ struct device_attribute *attr, char *buf)768778{769779 struct regulator_dev *rdev = dev_get_drvdata(dev);770780 struct regulator *regulator;···778788 regulator_unlock(rdev);779789 return sprintf(buf, "%d\n", uA);780790}781781-static DEVICE_ATTR(requested_microamps, 0444, regulator_total_uA_show, NULL);791791+static DEVICE_ATTR_RO(requested_microamps);782792783793static ssize_t num_users_show(struct device *dev, struct device_attribute *attr,784794 char *buf)···803813}804814static DEVICE_ATTR_RO(type);805815806806-static ssize_t regulator_suspend_mem_uV_show(struct device *dev,807807- struct device_attribute *attr, char *buf)816816+static ssize_t suspend_mem_microvolts_show(struct device *dev,817817+ struct device_attribute *attr, char *buf)808818{809819 struct regulator_dev *rdev = dev_get_drvdata(dev);810820811821 return sprintf(buf, "%d\n", rdev->constraints->state_mem.uV);812822}813813-static DEVICE_ATTR(suspend_mem_microvolts, 0444,814814- regulator_suspend_mem_uV_show, NULL);823823+static DEVICE_ATTR_RO(suspend_mem_microvolts);815824816816-static ssize_t regulator_suspend_disk_uV_show(struct device *dev,817817- struct device_attribute *attr, char *buf)825825+static ssize_t suspend_disk_microvolts_show(struct device *dev,826826+ struct device_attribute *attr, char *buf)818827{819828 struct regulator_dev *rdev = dev_get_drvdata(dev);820829821830 return sprintf(buf, "%d\n", rdev->constraints->state_disk.uV);822831}823823-static DEVICE_ATTR(suspend_disk_microvolts, 0444,824824- regulator_suspend_disk_uV_show, NULL);832832+static DEVICE_ATTR_RO(suspend_disk_microvolts);825833826826-static ssize_t regulator_suspend_standby_uV_show(struct device *dev,827827- struct device_attribute *attr, char *buf)834834+static ssize_t suspend_standby_microvolts_show(struct device *dev,835835+ struct device_attribute *attr, char *buf)828836{829837 struct regulator_dev *rdev = dev_get_drvdata(dev);830838831839 return sprintf(buf, "%d\n", rdev->constraints->state_standby.uV);832840}833833-static DEVICE_ATTR(suspend_standby_microvolts, 0444,834834- regulator_suspend_standby_uV_show, NULL);841841+static DEVICE_ATTR_RO(suspend_standby_microvolts);835842836836-static ssize_t regulator_suspend_mem_mode_show(struct device *dev,837837- struct device_attribute *attr, char *buf)843843+static ssize_t suspend_mem_mode_show(struct device *dev,844844+ struct device_attribute *attr, char *buf)838845{839846 struct regulator_dev *rdev = dev_get_drvdata(dev);840847841848 return regulator_print_opmode(buf,842849 rdev->constraints->state_mem.mode);843850}844844-static DEVICE_ATTR(suspend_mem_mode, 0444,845845- regulator_suspend_mem_mode_show, NULL);851851+static DEVICE_ATTR_RO(suspend_mem_mode);846852847847-static ssize_t regulator_suspend_disk_mode_show(struct device *dev,848848- struct device_attribute *attr, char *buf)853853+static ssize_t suspend_disk_mode_show(struct device *dev,854854+ struct device_attribute *attr, char *buf)849855{850856 struct regulator_dev *rdev = dev_get_drvdata(dev);851857852858 return regulator_print_opmode(buf,853859 rdev->constraints->state_disk.mode);854860}855855-static DEVICE_ATTR(suspend_disk_mode, 0444,856856- regulator_suspend_disk_mode_show, NULL);861861+static DEVICE_ATTR_RO(suspend_disk_mode);857862858858-static ssize_t regulator_suspend_standby_mode_show(struct device *dev,859859- struct device_attribute *attr, char *buf)863863+static ssize_t suspend_standby_mode_show(struct device *dev,864864+ struct device_attribute *attr, char *buf)860865{861866 struct regulator_dev *rdev = dev_get_drvdata(dev);862867863868 return regulator_print_opmode(buf,864869 rdev->constraints->state_standby.mode);865870}866866-static DEVICE_ATTR(suspend_standby_mode, 0444,867867- regulator_suspend_standby_mode_show, NULL);871871+static DEVICE_ATTR_RO(suspend_standby_mode);868872869869-static ssize_t regulator_suspend_mem_state_show(struct device *dev,870870- struct device_attribute *attr, char *buf)873873+static ssize_t suspend_mem_state_show(struct device *dev,874874+ struct device_attribute *attr, char *buf)871875{872876 struct regulator_dev *rdev = dev_get_drvdata(dev);873877874878 return regulator_print_state(buf,875879 rdev->constraints->state_mem.enabled);876880}877877-static DEVICE_ATTR(suspend_mem_state, 0444,878878- regulator_suspend_mem_state_show, NULL);881881+static DEVICE_ATTR_RO(suspend_mem_state);879882880880-static ssize_t regulator_suspend_disk_state_show(struct device *dev,881881- struct device_attribute *attr, char *buf)883883+static ssize_t suspend_disk_state_show(struct device *dev,884884+ struct device_attribute *attr, char *buf)882885{883886 struct regulator_dev *rdev = dev_get_drvdata(dev);884887885888 return regulator_print_state(buf,886889 rdev->constraints->state_disk.enabled);887890}888888-static DEVICE_ATTR(suspend_disk_state, 0444,889889- regulator_suspend_disk_state_show, NULL);891891+static DEVICE_ATTR_RO(suspend_disk_state);890892891891-static ssize_t regulator_suspend_standby_state_show(struct device *dev,892892- struct device_attribute *attr, char *buf)893893+static ssize_t suspend_standby_state_show(struct device *dev,894894+ struct device_attribute *attr, char *buf)893895{894896 struct regulator_dev *rdev = dev_get_drvdata(dev);895897896898 return regulator_print_state(buf,897899 rdev->constraints->state_standby.enabled);898900}899899-static DEVICE_ATTR(suspend_standby_state, 0444,900900- regulator_suspend_standby_state_show, NULL);901901+static DEVICE_ATTR_RO(suspend_standby_state);901902902902-static ssize_t regulator_bypass_show(struct device *dev,903903- struct device_attribute *attr, char *buf)903903+static ssize_t bypass_show(struct device *dev,904904+ struct device_attribute *attr, char *buf)904905{905906 struct regulator_dev *rdev = dev_get_drvdata(dev);906907 const char *report;···909928910929 return sprintf(buf, "%s\n", report);911930}912912-static DEVICE_ATTR(bypass, 0444,913913- regulator_bypass_show, NULL);931931+static DEVICE_ATTR_RO(bypass);914932915933/* Calculate the new optimum regulator operating mode based on the new total916934 * consumer load. All locks held by caller···1295131512961316static int _regulator_do_enable(struct regulator_dev *rdev);1297131713181318+static int notif_set_limit(struct regulator_dev *rdev,13191319+ int (*set)(struct regulator_dev *, int, int, bool),13201320+ int limit, int severity)13211321+{13221322+ bool enable;13231323+13241324+ if (limit == REGULATOR_NOTIF_LIMIT_DISABLE) {13251325+ enable = false;13261326+ limit = 0;13271327+ } else {13281328+ enable = true;13291329+ }13301330+13311331+ if (limit == REGULATOR_NOTIF_LIMIT_ENABLE)13321332+ limit = 0;13331333+13341334+ return set(rdev, limit, severity, enable);13351335+}13361336+13371337+static int handle_notify_limits(struct regulator_dev *rdev,13381338+ int (*set)(struct regulator_dev *, int, int, bool),13391339+ struct notification_limit *limits)13401340+{13411341+ int ret = 0;13421342+13431343+ if (!set)13441344+ return -EOPNOTSUPP;13451345+13461346+ if (limits->prot)13471347+ ret = notif_set_limit(rdev, set, limits->prot,13481348+ REGULATOR_SEVERITY_PROT);13491349+ if (ret)13501350+ return ret;13511351+13521352+ if (limits->err)13531353+ ret = notif_set_limit(rdev, set, limits->err,13541354+ REGULATOR_SEVERITY_ERR);13551355+ if (ret)13561356+ return ret;13571357+13581358+ if (limits->warn)13591359+ ret = notif_set_limit(rdev, set, limits->warn,13601360+ REGULATOR_SEVERITY_WARN);13611361+13621362+ return ret;13631363+}12981364/**12991365 * set_machine_constraints - sets regulator constraints13001366 * @rdev: regulator source···14261400 }14271401 }1428140214031403+ /*14041404+ * Existing logic does not warn if over_current_protection is given as14051405+ * a constraint but driver does not support that. I think we should14061406+ * warn about this type of issues as it is possible someone changes14071407+ * PMIC on board to another type - and the another PMIC's driver does14081408+ * not support setting protection. Board composer may happily believe14091409+ * the DT limits are respected - especially if the new PMIC HW also14101410+ * supports protection but the driver does not. I won't change the logic14111411+ * without hearing more experienced opinion on this though.14121412+ *14131413+ * If warning is seen as a good idea then we can merge handling the14141414+ * over-curret protection and detection and get rid of this special14151415+ * handling.14161416+ */14291417 if (rdev->constraints->over_current_protection14301418 && ops->set_over_current_protection) {14311431- ret = ops->set_over_current_protection(rdev);14191419+ int lim = rdev->constraints->over_curr_limits.prot;14201420+14211421+ ret = ops->set_over_current_protection(rdev, lim,14221422+ REGULATOR_SEVERITY_PROT,14231423+ true);14321424 if (ret < 0) {14331425 rdev_err(rdev, "failed to set over current protection: %pe\n",14341426 ERR_PTR(ret));14351427 return ret;14361428 }14291429+ }14301430+14311431+ if (rdev->constraints->over_current_detection)14321432+ ret = handle_notify_limits(rdev,14331433+ ops->set_over_current_protection,14341434+ &rdev->constraints->over_curr_limits);14351435+ if (ret) {14361436+ if (ret != -EOPNOTSUPP) {14371437+ rdev_err(rdev, "failed to set over current limits: %pe\n",14381438+ ERR_PTR(ret));14391439+ return ret;14401440+ }14411441+ rdev_warn(rdev,14421442+ "IC does not support requested over-current limits\n");14431443+ }14441444+14451445+ if (rdev->constraints->over_voltage_detection)14461446+ ret = handle_notify_limits(rdev,14471447+ ops->set_over_voltage_protection,14481448+ &rdev->constraints->over_voltage_limits);14491449+ if (ret) {14501450+ if (ret != -EOPNOTSUPP) {14511451+ rdev_err(rdev, "failed to set over voltage limits %pe\n",14521452+ ERR_PTR(ret));14531453+ return ret;14541454+ }14551455+ rdev_warn(rdev,14561456+ "IC does not support requested over voltage limits\n");14571457+ }14581458+14591459+ if (rdev->constraints->under_voltage_detection)14601460+ ret = handle_notify_limits(rdev,14611461+ ops->set_under_voltage_protection,14621462+ &rdev->constraints->under_voltage_limits);14631463+ if (ret) {14641464+ if (ret != -EOPNOTSUPP) {14651465+ rdev_err(rdev, "failed to set under voltage limits %pe\n",14661466+ ERR_PTR(ret));14671467+ return ret;14681468+ }14691469+ rdev_warn(rdev,14701470+ "IC does not support requested under voltage limits\n");14711471+ }14721472+14731473+ if (rdev->constraints->over_temp_detection)14741474+ ret = handle_notify_limits(rdev,14751475+ ops->set_thermal_protection,14761476+ &rdev->constraints->temp_limits);14771477+ if (ret) {14781478+ if (ret != -EOPNOTSUPP) {14791479+ rdev_err(rdev, "failed to set temperature limits %pe\n",14801480+ ERR_PTR(ret));14811481+ return ret;14821482+ }14831483+ rdev_warn(rdev,14841484+ "IC does not support requested temperature limits\n");14371485 }1438148614391487 if (rdev->constraints->active_discharge && ops->set_active_discharge) {···42114111}42124112EXPORT_SYMBOL_GPL(regulator_set_voltage_time_sel);4213411341144114+int regulator_sync_voltage_rdev(struct regulator_dev *rdev)41154115+{41164116+ int ret;41174117+41184118+ regulator_lock(rdev);41194119+41204120+ if (!rdev->desc->ops->set_voltage &&41214121+ !rdev->desc->ops->set_voltage_sel) {41224122+ ret = -EINVAL;41234123+ goto out;41244124+ }41254125+41264126+ /* balance only, if regulator is coupled */41274127+ if (rdev->coupling_desc.n_coupled > 1)41284128+ ret = regulator_balance_voltage(rdev, PM_SUSPEND_ON);41294129+ else41304130+ ret = -EOPNOTSUPP;41314131+41324132+out:41334133+ regulator_unlock(rdev);41344134+ return ret;41354135+}41364136+42144137/**42154138 * regulator_sync_voltage - re-apply last regulator output voltage42164139 * @regulator: regulator source···45094386}45104387EXPORT_SYMBOL_GPL(regulator_get_mode);4511438843894389+static int rdev_get_cached_err_flags(struct regulator_dev *rdev)43904390+{43914391+ int ret = 0;43924392+43934393+ if (rdev->use_cached_err) {43944394+ spin_lock(&rdev->err_lock);43954395+ ret = rdev->cached_err;43964396+ spin_unlock(&rdev->err_lock);43974397+ }43984398+ return ret;43994399+}44004400+45124401static int _regulator_get_error_flags(struct regulator_dev *rdev,45134402 unsigned int *flags)45144403{45154515- int ret;44044404+ int cached_flags, ret = 0;4516440545174406 regulator_lock(rdev);4518440745194519- /* sanity check */45204520- if (!rdev->desc->ops->get_error_flags) {45214521- ret = -EINVAL;45224522- goto out;45234523- }44084408+ cached_flags = rdev_get_cached_err_flags(rdev);4524440945254525- ret = rdev->desc->ops->get_error_flags(rdev, flags);45264526-out:44104410+ if (rdev->desc->ops->get_error_flags)44114411+ ret = rdev->desc->ops->get_error_flags(rdev, flags);44124412+ else if (!rdev->use_cached_err)44134413+ ret = -EINVAL;44144414+44154415+ *flags |= cached_flags;44164416+45274417 regulator_unlock(rdev);44184418+45284419 return ret;45294420}45304421···53715234 goto rinse;53725235 }53735236 device_initialize(&rdev->dev);52375237+ spin_lock_init(&rdev->err_lock);5374523853755239 /*53765240 * Duplicate the config so the driver could override it after
+2-1
drivers/regulator/da9052-regulator.c
···250250 case DA9052_ID_BUCK3:251251 case DA9052_ID_LDO2:252252 case DA9052_ID_LDO3:253253- ret = (new_sel - old_sel) * info->step_uV / 6250;253253+ ret = DIV_ROUND_UP(abs(new_sel - old_sel) * info->step_uV,254254+ 6250);254255 break;255256 }256257
+52
drivers/regulator/devres.c
···481481 WARN_ON(rc);482482}483483EXPORT_SYMBOL_GPL(devm_regulator_unregister_notifier);484484+485485+static void regulator_irq_helper_drop(void *res)486486+{487487+ regulator_irq_helper_cancel(&res);488488+}489489+490490+/**491491+ * devm_regulator_irq_helper - resource managed registration of IRQ based492492+ * regulator event/error notifier493493+ *494494+ * @dev: device to which lifetime the helper's lifetime is495495+ * bound.496496+ * @d: IRQ helper descriptor.497497+ * @irq: IRQ used to inform events/errors to be notified.498498+ * @irq_flags: Extra IRQ flags to be OR'ed with the default499499+ * IRQF_ONESHOT when requesting the (threaded) irq.500500+ * @common_errs: Errors which can be flagged by this IRQ for all rdevs.501501+ * When IRQ is re-enabled these errors will be cleared502502+ * from all associated regulators503503+ * @per_rdev_errs: Optional error flag array describing errors specific504504+ * for only some of the regulators. These errors will be505505+ * or'ed with common errors. If this is given the array506506+ * should contain rdev_amount flags. Can be set to NULL507507+ * if there is no regulator specific error flags for this508508+ * IRQ.509509+ * @rdev: Array of pointers to regulators associated with this510510+ * IRQ.511511+ * @rdev_amount: Amount of regulators associated with this IRQ.512512+ *513513+ * Return: handle to irq_helper or an ERR_PTR() encoded error code.514514+ */515515+void *devm_regulator_irq_helper(struct device *dev,516516+ const struct regulator_irq_desc *d, int irq,517517+ int irq_flags, int common_errs,518518+ int *per_rdev_errs,519519+ struct regulator_dev **rdev, int rdev_amount)520520+{521521+ void *ptr;522522+ int ret;523523+524524+ ptr = regulator_irq_helper(dev, d, irq, irq_flags, common_errs,525525+ per_rdev_errs, rdev, rdev_amount);526526+ if (IS_ERR(ptr))527527+ return ptr;528528+529529+ ret = devm_add_action_or_reset(dev, regulator_irq_helper_drop, ptr);530530+ if (ret)531531+ return ERR_PTR(ret);532532+533533+ return ptr;534534+}535535+EXPORT_SYMBOL_GPL(devm_regulator_irq_helper);
···11+// SPDX-License-Identifier: GPL-2.022+//33+// Copyright (C) 2021 ROHM Semiconductors44+// regulator IRQ based event notification helpers55+//66+// Logic has been partially adapted from qcom-labibb driver.77+//88+// Author: Matti Vaittinen <matti.vaittinen@fi.rohmeurope.com>99+1010+#include <linux/device.h>1111+#include <linux/err.h>1212+#include <linux/interrupt.h>1313+#include <linux/kernel.h>1414+#include <linux/reboot.h>1515+#include <linux/regmap.h>1616+#include <linux/slab.h>1717+#include <linux/spinlock.h>1818+#include <linux/regulator/driver.h>1919+2020+#include "internal.h"2121+2222+#define REGULATOR_FORCED_SAFETY_SHUTDOWN_WAIT_MS 100002323+2424+struct regulator_irq {2525+ struct regulator_irq_data rdata;2626+ struct regulator_irq_desc desc;2727+ int irq;2828+ int retry_cnt;2929+ struct delayed_work isr_work;3030+};3131+3232+/*3333+ * Should only be called from threaded handler to prevent potential deadlock3434+ */3535+static void rdev_flag_err(struct regulator_dev *rdev, int err)3636+{3737+ spin_lock(&rdev->err_lock);3838+ rdev->cached_err |= err;3939+ spin_unlock(&rdev->err_lock);4040+}4141+4242+static void rdev_clear_err(struct regulator_dev *rdev, int err)4343+{4444+ spin_lock(&rdev->err_lock);4545+ rdev->cached_err &= ~err;4646+ spin_unlock(&rdev->err_lock);4747+}4848+4949+static void regulator_notifier_isr_work(struct work_struct *work)5050+{5151+ struct regulator_irq *h;5252+ struct regulator_irq_desc *d;5353+ struct regulator_irq_data *rid;5454+ int ret = 0;5555+ int tmo, i;5656+ int num_rdevs;5757+5858+ h = container_of(work, struct regulator_irq,5959+ isr_work.work);6060+ d = &h->desc;6161+ rid = &h->rdata;6262+ num_rdevs = rid->num_states;6363+6464+reread:6565+ if (d->fatal_cnt && h->retry_cnt > d->fatal_cnt) {6666+ if (!d->die)6767+ return hw_protection_shutdown("Regulator HW failure? - no IC recovery",6868+ REGULATOR_FORCED_SAFETY_SHUTDOWN_WAIT_MS);6969+ ret = d->die(rid);7070+ /*7171+ * If the 'last resort' IC recovery failed we will have7272+ * nothing else left to do...7373+ */7474+ if (ret)7575+ return hw_protection_shutdown("Regulator HW failure. IC recovery failed",7676+ REGULATOR_FORCED_SAFETY_SHUTDOWN_WAIT_MS);7777+7878+ /*7979+ * If h->die() was implemented we assume recovery has been8080+ * attempted (probably regulator was shut down) and we8181+ * just enable IRQ and bail-out.8282+ */8383+ goto enable_out;8484+ }8585+ if (d->renable) {8686+ ret = d->renable(rid);8787+8888+ if (ret == REGULATOR_FAILED_RETRY) {8989+ /* Driver could not get current status */9090+ h->retry_cnt++;9191+ if (!d->reread_ms)9292+ goto reread;9393+9494+ tmo = d->reread_ms;9595+ goto reschedule;9696+ }9797+9898+ if (ret) {9999+ /*100100+ * IC status reading succeeded. update error info101101+ * just in case the renable changed it.102102+ */103103+ for (i = 0; i < num_rdevs; i++) {104104+ struct regulator_err_state *stat;105105+ struct regulator_dev *rdev;106106+107107+ stat = &rid->states[i];108108+ rdev = stat->rdev;109109+ rdev_clear_err(rdev, (~stat->errors) &110110+ stat->possible_errs);111111+ }112112+ h->retry_cnt++;113113+ /*114114+ * The IC indicated problem is still ON - no point in115115+ * re-enabling the IRQ. Retry later.116116+ */117117+ tmo = d->irq_off_ms;118118+ goto reschedule;119119+ }120120+ }121121+122122+ /*123123+ * Either IC reported problem cleared or no status checker was provided.124124+ * If problems are gone - good. If not - then the IRQ will fire again125125+ * and we'll have a new nice loop. In any case we should clear error126126+ * flags here and re-enable IRQs.127127+ */128128+ for (i = 0; i < num_rdevs; i++) {129129+ struct regulator_err_state *stat;130130+ struct regulator_dev *rdev;131131+132132+ stat = &rid->states[i];133133+ rdev = stat->rdev;134134+ rdev_clear_err(rdev, stat->possible_errs);135135+ }136136+137137+ /*138138+ * Things have been seemingly successful => zero retry-counter.139139+ */140140+ h->retry_cnt = 0;141141+142142+enable_out:143143+ enable_irq(h->irq);144144+145145+ return;146146+147147+reschedule:148148+ if (!d->high_prio)149149+ mod_delayed_work(system_wq, &h->isr_work,150150+ msecs_to_jiffies(tmo));151151+ else152152+ mod_delayed_work(system_highpri_wq, &h->isr_work,153153+ msecs_to_jiffies(tmo));154154+}155155+156156+static irqreturn_t regulator_notifier_isr(int irq, void *data)157157+{158158+ struct regulator_irq *h = data;159159+ struct regulator_irq_desc *d;160160+ struct regulator_irq_data *rid;161161+ unsigned long rdev_map = 0;162162+ int num_rdevs;163163+ int ret, i;164164+165165+ d = &h->desc;166166+ rid = &h->rdata;167167+ num_rdevs = rid->num_states;168168+169169+ if (d->fatal_cnt)170170+ h->retry_cnt++;171171+172172+ /*173173+ * we spare a few cycles by not clearing statuses prior to this call.174174+ * The IC driver must initialize the status buffers for rdevs175175+ * which it indicates having active events via rdev_map.176176+ *177177+ * Maybe we should just to be on a safer side(?)178178+ */179179+ ret = d->map_event(irq, rid, &rdev_map);180180+181181+ /*182182+ * If status reading fails (which is unlikely) we don't ack/disable183183+ * IRQ but just increase fail count and retry when IRQ fires again.184184+ * If retry_count exceeds the given safety limit we call IC specific die185185+ * handler which can try disabling regulator(s).186186+ *187187+ * If no die handler is given we will just bug() as a last resort.188188+ *189189+ * We could try disabling all associated rdevs - but we might shoot190190+ * ourselves in the head and leave the problematic regulator enabled. So191191+ * if IC has no die-handler populated we just assume the regulator192192+ * can't be disabled.193193+ */194194+ if (unlikely(ret == REGULATOR_FAILED_RETRY))195195+ goto fail_out;196196+197197+ h->retry_cnt = 0;198198+ /*199199+ * Let's not disable IRQ if there were no status bits for us. We'd200200+ * better leave spurious IRQ handling to genirq201201+ */202202+ if (ret || !rdev_map)203203+ return IRQ_NONE;204204+205205+ /*206206+ * Some events are bogus if the regulator is disabled. Skip such events207207+ * if all relevant regulators are disabled208208+ */209209+ if (d->skip_off) {210210+ for_each_set_bit(i, &rdev_map, num_rdevs) {211211+ struct regulator_dev *rdev;212212+ const struct regulator_ops *ops;213213+214214+ rdev = rid->states[i].rdev;215215+ ops = rdev->desc->ops;216216+217217+ /*218218+ * If any of the flagged regulators is enabled we do219219+ * handle this220220+ */221221+ if (ops->is_enabled(rdev))222222+ break;223223+ }224224+ if (i == num_rdevs)225225+ return IRQ_NONE;226226+ }227227+228228+ /* Disable IRQ if HW keeps line asserted */229229+ if (d->irq_off_ms)230230+ disable_irq_nosync(irq);231231+232232+ /*233233+ * IRQ seems to be for us. Let's fire correct notifiers / store error234234+ * flags235235+ */236236+ for_each_set_bit(i, &rdev_map, num_rdevs) {237237+ struct regulator_err_state *stat;238238+ struct regulator_dev *rdev;239239+240240+ stat = &rid->states[i];241241+ rdev = stat->rdev;242242+243243+ rdev_dbg(rdev, "Sending regulator notification EVT 0x%lx\n",244244+ stat->notifs);245245+246246+ regulator_notifier_call_chain(rdev, stat->notifs, NULL);247247+ rdev_flag_err(rdev, stat->errors);248248+ }249249+250250+ if (d->irq_off_ms) {251251+ if (!d->high_prio)252252+ schedule_delayed_work(&h->isr_work,253253+ msecs_to_jiffies(d->irq_off_ms));254254+ else255255+ mod_delayed_work(system_highpri_wq,256256+ &h->isr_work,257257+ msecs_to_jiffies(d->irq_off_ms));258258+ }259259+260260+ return IRQ_HANDLED;261261+262262+fail_out:263263+ if (d->fatal_cnt && h->retry_cnt > d->fatal_cnt) {264264+ /* If we have no recovery, just try shut down straight away */265265+ if (!d->die) {266266+ hw_protection_shutdown("Regulator failure. Retry count exceeded",267267+ REGULATOR_FORCED_SAFETY_SHUTDOWN_WAIT_MS);268268+ } else {269269+ ret = d->die(rid);270270+ /* If die() failed shut down as a last attempt to save the HW */271271+ if (ret)272272+ hw_protection_shutdown("Regulator failure. Recovery failed",273273+ REGULATOR_FORCED_SAFETY_SHUTDOWN_WAIT_MS);274274+ }275275+ }276276+277277+ return IRQ_NONE;278278+}279279+280280+static int init_rdev_state(struct device *dev, struct regulator_irq *h,281281+ struct regulator_dev **rdev, int common_err,282282+ int *rdev_err, int rdev_amount)283283+{284284+ int i;285285+286286+ h->rdata.states = devm_kzalloc(dev, sizeof(*h->rdata.states) *287287+ rdev_amount, GFP_KERNEL);288288+ if (!h->rdata.states)289289+ return -ENOMEM;290290+291291+ h->rdata.num_states = rdev_amount;292292+ h->rdata.data = h->desc.data;293293+294294+ for (i = 0; i < rdev_amount; i++) {295295+ h->rdata.states[i].possible_errs = common_err;296296+ if (rdev_err)297297+ h->rdata.states[i].possible_errs |= *rdev_err++;298298+ h->rdata.states[i].rdev = *rdev++;299299+ }300300+301301+ return 0;302302+}303303+304304+static void init_rdev_errors(struct regulator_irq *h)305305+{306306+ int i;307307+308308+ for (i = 0; i < h->rdata.num_states; i++)309309+ if (h->rdata.states[i].possible_errs)310310+ h->rdata.states[i].rdev->use_cached_err = true;311311+}312312+313313+/**314314+ * regulator_irq_helper - register IRQ based regulator event/error notifier315315+ *316316+ * @dev: device providing the IRQs317317+ * @d: IRQ helper descriptor.318318+ * @irq: IRQ used to inform events/errors to be notified.319319+ * @irq_flags: Extra IRQ flags to be OR'ed with the default320320+ * IRQF_ONESHOT when requesting the (threaded) irq.321321+ * @common_errs: Errors which can be flagged by this IRQ for all rdevs.322322+ * When IRQ is re-enabled these errors will be cleared323323+ * from all associated regulators324324+ * @per_rdev_errs: Optional error flag array describing errors specific325325+ * for only some of the regulators. These errors will be326326+ * or'ed with common errors. If this is given the array327327+ * should contain rdev_amount flags. Can be set to NULL328328+ * if there is no regulator specific error flags for this329329+ * IRQ.330330+ * @rdev: Array of pointers to regulators associated with this331331+ * IRQ.332332+ * @rdev_amount: Amount of regulators associated with this IRQ.333333+ *334334+ * Return: handle to irq_helper or an ERR_PTR() encoded error code.335335+ */336336+void *regulator_irq_helper(struct device *dev,337337+ const struct regulator_irq_desc *d, int irq,338338+ int irq_flags, int common_errs, int *per_rdev_errs,339339+ struct regulator_dev **rdev, int rdev_amount)340340+{341341+ struct regulator_irq *h;342342+ int ret;343343+344344+ if (!rdev_amount || !d || !d->map_event || !d->name)345345+ return ERR_PTR(-EINVAL);346346+347347+ h = devm_kzalloc(dev, sizeof(*h), GFP_KERNEL);348348+ if (!h)349349+ return ERR_PTR(-ENOMEM);350350+351351+ h->irq = irq;352352+ h->desc = *d;353353+354354+ ret = init_rdev_state(dev, h, rdev, common_errs, per_rdev_errs,355355+ rdev_amount);356356+ if (ret)357357+ return ERR_PTR(ret);358358+359359+ init_rdev_errors(h);360360+361361+ if (h->desc.irq_off_ms)362362+ INIT_DELAYED_WORK(&h->isr_work, regulator_notifier_isr_work);363363+364364+ ret = request_threaded_irq(h->irq, NULL, regulator_notifier_isr,365365+ IRQF_ONESHOT | irq_flags, h->desc.name, h);366366+ if (ret) {367367+ dev_err(dev, "Failed to request IRQ %d\n", irq);368368+369369+ return ERR_PTR(ret);370370+ }371371+372372+ return h;373373+}374374+EXPORT_SYMBOL_GPL(regulator_irq_helper);375375+376376+/**377377+ * regulator_irq_helper_cancel - drop IRQ based regulator event/error notifier378378+ *379379+ * @handle: Pointer to handle returned by a successful call to380380+ * regulator_irq_helper(). Will be NULLed upon return.381381+ *382382+ * The associated IRQ is released and work is cancelled when the function383383+ * returns.384384+ */385385+void regulator_irq_helper_cancel(void **handle)386386+{387387+ if (handle && *handle) {388388+ struct regulator_irq *h = *handle;389389+390390+ free_irq(h->irq, h);391391+ if (h->desc.irq_off_ms)392392+ cancel_delayed_work_sync(&h->isr_work);393393+394394+ h = NULL;395395+ }396396+}397397+EXPORT_SYMBOL_GPL(regulator_irq_helper_cancel);
···307307 return IRQ_HANDLED;308308}309309310310-static int qcom_labibb_set_ocp(struct regulator_dev *rdev)310310+static int qcom_labibb_set_ocp(struct regulator_dev *rdev, int lim,311311+ int severity, bool enable)311312{312313 struct labibb_regulator *vreg = rdev_get_drvdata(rdev);313314 char *ocp_irq_name;314315 u32 irq_flags = IRQF_ONESHOT;315316 int irq_trig_low, ret;317317+318318+ /*319319+ * labibb supports only protection - and does not support setting320320+ * limit. Furthermore, we don't support disabling protection.321321+ */322322+ if (lim || severity != REGULATOR_SEVERITY_PROT || !enable)323323+ return -EINVAL;316324317325 /* If there is no OCP interrupt, there's nothing to set */318326 if (vreg->ocp_irq <= 0)
···32323333static int stpmic1_set_mode(struct regulator_dev *rdev, unsigned int mode);3434static unsigned int stpmic1_get_mode(struct regulator_dev *rdev);3535-static int stpmic1_set_icc(struct regulator_dev *rdev);3535+static int stpmic1_set_icc(struct regulator_dev *rdev, int lim, int severity,3636+ bool enable);3637static unsigned int stpmic1_map_mode(unsigned int mode);37383839enum {···492491 STPMIC1_BUCK_MODE_LP, value);493492}494493495495-static int stpmic1_set_icc(struct regulator_dev *rdev)494494+static int stpmic1_set_icc(struct regulator_dev *rdev, int lim, int severity,495495+ bool enable)496496{497497 struct stpmic1_regulator_cfg *cfg = rdev_get_drvdata(rdev);498498 struct regmap *regmap = rdev_get_regmap(rdev);499499+500500+ /*501501+ * The code seems like one bit in a register controls whether OCP is502502+ * enabled. So we might be able to turn it off here is if that503503+ * was requested. I won't support this because I don't have the HW.504504+ * Feel free to try and implement if you have the HW and need kernel505505+ * to disable this.506506+ *507507+ * Also, I don't know if limit can be configured or if we support508508+ * error/warning instead of protect. So I just keep existing logic509509+ * and assume no.510510+ */511511+ if (lim || severity != REGULATOR_SEVERITY_PROT || !enable)512512+ return -EINVAL;499513500514 /* enable switch off in case of over current */501515 return regmap_update_bits(regmap, cfg->icc_reg, cfg->icc_mask,
+128
drivers/regulator/sy7636a-regulator.c
···11+// SPDX-License-Identifier: GPL-2.0+22+//33+// Functions to access SY3686A power management chip voltages44+//55+// Copyright (C) 2019 reMarkable AS - http://www.remarkable.com/66+//77+// Authors: Lars Ivar Miljeteig <lars.ivar.miljeteig@remarkable.com>88+// Alistair Francis <alistair@alistair23.me>99+1010+#include <linux/module.h>1111+#include <linux/platform_device.h>1212+#include <linux/regmap.h>1313+#include <linux/gpio/consumer.h>1414+#include <linux/mfd/sy7636a.h>1515+1616+#define SY7636A_POLL_ENABLED_TIME 5001717+1818+static int sy7636a_get_vcom_voltage_op(struct regulator_dev *rdev)1919+{2020+ int ret;2121+ unsigned int val, val_h;2222+2323+ ret = regmap_read(rdev->regmap, SY7636A_REG_VCOM_ADJUST_CTRL_L, &val);2424+ if (ret)2525+ return ret;2626+2727+ ret = regmap_read(rdev->regmap, SY7636A_REG_VCOM_ADJUST_CTRL_H, &val_h);2828+ if (ret)2929+ return ret;3030+3131+ val |= (val_h << VCOM_ADJUST_CTRL_SHIFT);3232+3333+ return (val & VCOM_ADJUST_CTRL_MASK) * VCOM_ADJUST_CTRL_SCAL;3434+}3535+3636+static int sy7636a_get_status(struct regulator_dev *rdev)3737+{3838+ struct sy7636a *sy7636a = rdev_get_drvdata(rdev);3939+ int ret = 0;4040+4141+ ret = gpiod_get_value_cansleep(sy7636a->pgood_gpio);4242+ if (ret < 0)4343+ dev_err(&rdev->dev, "Failed to read pgood gpio: %d\n", ret);4444+4545+ return ret;4646+}4747+4848+static const struct regulator_ops sy7636a_vcom_volt_ops = {4949+ .get_voltage = sy7636a_get_vcom_voltage_op,5050+ .enable = regulator_enable_regmap,5151+ .disable = regulator_disable_regmap,5252+ .is_enabled = regulator_is_enabled_regmap,5353+ .get_status = sy7636a_get_status,5454+};5555+5656+static const struct regulator_desc desc = {5757+ .name = "vcom",5858+ .id = 0,5959+ .ops = &sy7636a_vcom_volt_ops,6060+ .type = REGULATOR_VOLTAGE,6161+ .owner = THIS_MODULE,6262+ .enable_reg = SY7636A_REG_OPERATION_MODE_CRL,6363+ .enable_mask = SY7636A_OPERATION_MODE_CRL_ONOFF,6464+ .poll_enabled_time = SY7636A_POLL_ENABLED_TIME,6565+ .regulators_node = of_match_ptr("regulators"),6666+ .of_match = of_match_ptr("vcom"),6767+};6868+6969+static int sy7636a_regulator_probe(struct platform_device *pdev)7070+{7171+ struct sy7636a *sy7636a = dev_get_drvdata(pdev->dev.parent);7272+ struct regulator_config config = { };7373+ struct regulator_dev *rdev;7474+ struct gpio_desc *gdp;7575+ int ret;7676+7777+ if (!sy7636a)7878+ return -EPROBE_DEFER;7979+8080+ platform_set_drvdata(pdev, sy7636a);8181+8282+ gdp = devm_gpiod_get(sy7636a->dev, "epd-pwr-good", GPIOD_IN);8383+ if (IS_ERR(gdp)) {8484+ dev_err(sy7636a->dev, "Power good GPIO fault %ld\n", PTR_ERR(gdp));8585+ return PTR_ERR(gdp);8686+ }8787+8888+ sy7636a->pgood_gpio = gdp;8989+9090+ ret = regmap_write(sy7636a->regmap, SY7636A_REG_POWER_ON_DELAY_TIME, 0x0);9191+ if (ret) {9292+ dev_err(sy7636a->dev, "Failed to initialize regulator: %d\n", ret);9393+ return ret;9494+ }9595+9696+ config.dev = &pdev->dev;9797+ config.dev->of_node = sy7636a->dev->of_node;9898+ config.driver_data = sy7636a;9999+ config.regmap = sy7636a->regmap;100100+101101+ rdev = devm_regulator_register(&pdev->dev, &desc, &config);102102+ if (IS_ERR(rdev)) {103103+ dev_err(sy7636a->dev, "Failed to register %s regulator\n",104104+ pdev->name);105105+ return PTR_ERR(rdev);106106+ }107107+108108+ return 0;109109+}110110+111111+static const struct platform_device_id sy7636a_regulator_id_table[] = {112112+ { "sy7636a-regulator", },113113+ { }114114+};115115+MODULE_DEVICE_TABLE(platform, sy7636a_regulator_id_table);116116+117117+static struct platform_driver sy7636a_regulator_driver = {118118+ .driver = {119119+ .name = "sy7636a-regulator",120120+ },121121+ .probe = sy7636a_regulator_probe,122122+ .id_table = sy7636a_regulator_id_table,123123+};124124+module_platform_driver(sy7636a_regulator_driver);125125+126126+MODULE_AUTHOR("Lars Ivar Miljeteig <lars.ivar.miljeteig@remarkable.com>");127127+MODULE_DESCRIPTION("SY7636A voltage regulator driver");128128+MODULE_LICENSE("GPL v2");
···36363737static DEFINE_MUTEX(thermal_list_lock);3838static DEFINE_MUTEX(thermal_governor_lock);3939-static DEFINE_MUTEX(poweroff_lock);40394140static atomic_t in_suspend;4242-static bool power_off_triggered;43414442static struct thermal_governor *def_governor;4543···325327 def_governor->throttle(tz, trip);326328}327329328328-/**329329- * thermal_emergency_poweroff_func - emergency poweroff work after a known delay330330- * @work: work_struct associated with the emergency poweroff function331331- *332332- * This function is called in very critical situations to force333333- * a kernel poweroff after a configurable timeout value.334334- */335335-static void thermal_emergency_poweroff_func(struct work_struct *work)336336-{337337- /*338338- * We have reached here after the emergency thermal shutdown339339- * Waiting period has expired. This means orderly_poweroff has340340- * not been able to shut off the system for some reason.341341- * Try to shut down the system immediately using kernel_power_off342342- * if populated343343- */344344- WARN(1, "Attempting kernel_power_off: Temperature too high\n");345345- kernel_power_off();346346-347347- /*348348- * Worst of the worst case trigger emergency restart349349- */350350- WARN(1, "Attempting emergency_restart: Temperature too high\n");351351- emergency_restart();352352-}353353-354354-static DECLARE_DELAYED_WORK(thermal_emergency_poweroff_work,355355- thermal_emergency_poweroff_func);356356-357357-/**358358- * thermal_emergency_poweroff - Trigger an emergency system poweroff359359- *360360- * This may be called from any critical situation to trigger a system shutdown361361- * after a known period of time. By default this is not scheduled.362362- */363363-static void thermal_emergency_poweroff(void)364364-{365365- int poweroff_delay_ms = CONFIG_THERMAL_EMERGENCY_POWEROFF_DELAY_MS;366366- /*367367- * poweroff_delay_ms must be a carefully profiled positive value.368368- * Its a must for thermal_emergency_poweroff_work to be scheduled369369- */370370- if (poweroff_delay_ms <= 0)371371- return;372372- schedule_delayed_work(&thermal_emergency_poweroff_work,373373- msecs_to_jiffies(poweroff_delay_ms));374374-}375375-376330void thermal_zone_device_critical(struct thermal_zone_device *tz)377331{332332+ /*333333+ * poweroff_delay_ms must be a carefully profiled positive value.334334+ * Its a must for forced_emergency_poweroff_work to be scheduled.335335+ */336336+ int poweroff_delay_ms = CONFIG_THERMAL_EMERGENCY_POWEROFF_DELAY_MS;337337+378338 dev_emerg(&tz->device, "%s: critical temperature reached, "379339 "shutting down\n", tz->type);380340381381- mutex_lock(&poweroff_lock);382382- if (!power_off_triggered) {383383- /*384384- * Queue a backup emergency shutdown in the event of385385- * orderly_poweroff failure386386- */387387- thermal_emergency_poweroff();388388- orderly_poweroff(true);389389- power_off_triggered = true;390390- }391391- mutex_unlock(&poweroff_lock);341341+ hw_protection_shutdown("Temperature too high", poweroff_delay_ms);392342}393343EXPORT_SYMBOL(thermal_zone_device_critical);394344···14841538 ida_destroy(&thermal_cdev_ida);14851539 mutex_destroy(&thermal_list_lock);14861540 mutex_destroy(&thermal_governor_lock);14871487- mutex_destroy(&poweroff_lock);14881541 return result;14891542}14901543postcore_initcall(thermal_init);
···79798080extern void orderly_poweroff(bool force);8181extern void orderly_reboot(void);8282+void hw_protection_shutdown(const char *reason, int ms_until_forced);82838384/*8485 * Emergency restart, callable from an interrupt handler.
+14
include/linux/regulator/consumer.h
···119119#define REGULATOR_EVENT_PRE_DISABLE 0x400120120#define REGULATOR_EVENT_ABORT_DISABLE 0x800121121#define REGULATOR_EVENT_ENABLE 0x1000122122+/*123123+ * Following notifications should be emitted only if detected condition124124+ * is such that the HW is likely to still be working but consumers should125125+ * take a recovery action to prevent problems esacalating into errors.126126+ */127127+#define REGULATOR_EVENT_UNDER_VOLTAGE_WARN 0x2000128128+#define REGULATOR_EVENT_OVER_CURRENT_WARN 0x4000129129+#define REGULATOR_EVENT_OVER_VOLTAGE_WARN 0x8000130130+#define REGULATOR_EVENT_OVER_TEMP_WARN 0x10000131131+#define REGULATOR_EVENT_WARN_MASK 0x1E000122132123133/*124134 * Regulator errors that can be queried using regulator_get_error_flags···148138#define REGULATOR_ERROR_FAIL BIT(4)149139#define REGULATOR_ERROR_OVER_TEMP BIT(5)150140141141+#define REGULATOR_ERROR_UNDER_VOLTAGE_WARN BIT(6)142142+#define REGULATOR_ERROR_OVER_CURRENT_WARN BIT(7)143143+#define REGULATOR_ERROR_OVER_VOLTAGE_WARN BIT(8)144144+#define REGULATOR_ERROR_OVER_TEMP_WARN BIT(9)151145152146/**153147 * struct pre_voltage_change_data - Data sent with PRE_VOLTAGE_CHANGE event
-5
include/linux/regulator/coupler.h
···52525353#ifdef CONFIG_REGULATOR5454int regulator_coupler_register(struct regulator_coupler *coupler);5555-const char *rdev_get_name(struct regulator_dev *rdev);5655int regulator_check_consumers(struct regulator_dev *rdev,5756 int *min_uV, int *max_uV,5857 suspend_state_t state);···6768static inline int regulator_coupler_register(struct regulator_coupler *coupler)6869{6970 return 0;7070-}7171-static inline const char *rdev_get_name(struct regulator_dev *rdev)7272-{7373- return NULL;7471}7572static inline int regulator_check_consumers(struct regulator_dev *rdev,7673 int *min_uV, int *max_uV,
+183-4
include/linux/regulator/driver.h
···4040 REGULATOR_STATUS_UNDEFINED,4141};42424343+enum regulator_detection_severity {4444+ /* Hardware shut down voltage outputs if condition is detected */4545+ REGULATOR_SEVERITY_PROT,4646+ /* Hardware is probably damaged/inoperable */4747+ REGULATOR_SEVERITY_ERR,4848+ /* Hardware is still recoverable but recovery action must be taken */4949+ REGULATOR_SEVERITY_WARN,5050+};5151+4352/* Initialize struct linear_range for regulators */4453#define REGULATOR_LINEAR_RANGE(_min_uV, _min_sel, _max_sel, _step_uV) \4554{ \···8778 * @get_current_limit: Get the configured limit for a current-limited regulator.8879 * @set_input_current_limit: Configure an input limit.8980 *9090- * @set_over_current_protection: Support capability of automatically shutting9191- * down when detecting an over current event.8181+ * @set_over_current_protection: Support enabling of and setting limits for over8282+ * current situation detection. Detection can be configured for three8383+ * levels of severity.8484+ * REGULATOR_SEVERITY_PROT should automatically shut down the regulator(s).8585+ * REGULATOR_SEVERITY_ERR should indicate that over-current situation is8686+ * caused by an unrecoverable error but HW does not perform8787+ * automatic shut down.8888+ * REGULATOR_SEVERITY_WARN should indicate situation where hardware is8989+ * still believed to not be damaged but that a board sepcific9090+ * recovery action is needed. If lim_uA is 0 the limit should not9191+ * be changed but the detection should just be enabled/disabled as9292+ * is requested.9393+ * @set_over_voltage_protection: Support enabling of and setting limits for over9494+ * voltage situation detection. Detection can be configured for same9595+ * severities as over current protection.9696+ * @set_under_voltage_protection: Support enabling of and setting limits for9797+ * under situation detection.9898+ * @set_thermal_protection: Support enabling of and setting limits for over9999+ * temperature situation detection.92100 *93101 * @set_active_discharge: Set active discharge enable/disable of regulators.94102 *···169143 int (*get_current_limit) (struct regulator_dev *);170144171145 int (*set_input_current_limit) (struct regulator_dev *, int lim_uA);172172- int (*set_over_current_protection) (struct regulator_dev *);173173- int (*set_active_discharge) (struct regulator_dev *, bool enable);146146+ int (*set_over_current_protection)(struct regulator_dev *, int lim_uA,147147+ int severity, bool enable);148148+ int (*set_over_voltage_protection)(struct regulator_dev *, int lim_uV,149149+ int severity, bool enable);150150+ int (*set_under_voltage_protection)(struct regulator_dev *, int lim_uV,151151+ int severity, bool enable);152152+ int (*set_thermal_protection)(struct regulator_dev *, int lim,153153+ int severity, bool enable);154154+ int (*set_active_discharge)(struct regulator_dev *, bool enable);174155175156 /* enable/disable regulator */176157 int (*enable) (struct regulator_dev *);···446413 struct gpio_desc *ena_gpiod;447414};448415416416+/**417417+ * struct regulator_err_state - regulator error/notification status418418+ *419419+ * @rdev: Regulator which status the struct indicates.420420+ * @notifs: Events which have occurred on the regulator.421421+ * @errors: Errors which are active on the regulator.422422+ * @possible_errs: Errors which can be signaled (by given IRQ).423423+ */424424+struct regulator_err_state {425425+ struct regulator_dev *rdev;426426+ unsigned long notifs;427427+ unsigned long errors;428428+ int possible_errs;429429+};430430+431431+/**432432+ * struct regulator_irq_data - regulator error/notification status date433433+ *434434+ * @states: Status structs for each of the associated regulators.435435+ * @num_states: Amount of associated regulators.436436+ * @data: Driver data pointer given at regulator_irq_desc.437437+ * @opaque: Value storage for IC driver. Core does not update this. ICs438438+ * may want to store status register value here at map_event and439439+ * compare contents at 'renable' callback to see if new problems440440+ * have been added to status. If that is the case it may be441441+ * desirable to return REGULATOR_ERROR_CLEARED and not442442+ * REGULATOR_ERROR_ON to allow IRQ fire again and to generate443443+ * notifications also for the new issues.444444+ *445445+ * This structure is passed to 'map_event' and 'renable' callbacks for446446+ * reporting regulator status to core.447447+ */448448+struct regulator_irq_data {449449+ struct regulator_err_state *states;450450+ int num_states;451451+ void *data;452452+ long opaque;453453+};454454+455455+/**456456+ * struct regulator_irq_desc - notification sender for IRQ based events.457457+ *458458+ * @name: The visible name for the IRQ459459+ * @fatal_cnt: If this IRQ is used to signal HW damaging condition it may be460460+ * best to shut-down regulator(s) or reboot the SOC if error461461+ * handling is repeatedly failing. If fatal_cnt is given the IRQ462462+ * handling is aborted if it fails for fatal_cnt times and die()463463+ * callback (if populated) or BUG() is called to try to prevent464464+ * further damage.465465+ * @reread_ms: The time which is waited before attempting to re-read status466466+ * at the worker if IC reading fails. Immediate re-read is done467467+ * if time is not specified.468468+ * @irq_off_ms: The time which IRQ is kept disabled before re-evaluating the469469+ * status for devices which keep IRQ disabled for duration of the470470+ * error. If this is not given the IRQ is left enabled and renable471471+ * is not called.472472+ * @skip_off: If set to true the IRQ handler will attempt to check if any of473473+ * the associated regulators are enabled prior to taking other474474+ * actions. If no regulators are enabled and this is set to true475475+ * a spurious IRQ is assumed and IRQ_NONE is returned.476476+ * @high_prio: Boolean to indicate that high priority WQ should be used.477477+ * @data: Driver private data pointer which will be passed as such to478478+ * the renable, map_event and die callbacks in regulator_irq_data.479479+ * @die: Protection callback. If IC status reading or recovery actions480480+ * fail fatal_cnt times this callback or BUG() is called. This481481+ * callback should implement a final protection attempt like482482+ * disabling the regulator. If protection succeeded this may483483+ * return 0. If anything else is returned the core assumes final484484+ * protection failed and calls BUG() as a last resort.485485+ * @map_event: Driver callback to map IRQ status into regulator devices with486486+ * events / errors. NOTE: callback MUST initialize both the487487+ * errors and notifs for all rdevs which it signals having488488+ * active events as core does not clean the map data.489489+ * REGULATOR_FAILED_RETRY can be returned to indicate that the490490+ * status reading from IC failed. If this is repeated for491491+ * fatal_cnt times the core will call die() callback or BUG()492492+ * as a last resort to protect the HW.493493+ * @renable: Optional callback to check status (if HW supports that) before494494+ * re-enabling IRQ. If implemented this should clear the error495495+ * flags so that errors fetched by regulator_get_error_flags()496496+ * are updated. If callback is not implemented then errors are497497+ * assumed to be cleared and IRQ is re-enabled.498498+ * REGULATOR_FAILED_RETRY can be returned to499499+ * indicate that the status reading from IC failed. If this is500500+ * repeated for 'fatal_cnt' times the core will call die()501501+ * callback or BUG() as a last resort to protect the HW.502502+ * Returning zero indicates that the problem in HW has been solved503503+ * and IRQ will be re-enabled. Returning REGULATOR_ERROR_ON504504+ * indicates the error condition is still active and keeps IRQ505505+ * disabled. Please note that returning REGULATOR_ERROR_ON does506506+ * not retrigger evaluating what events are active or resending507507+ * notifications. If this is needed you probably want to return508508+ * zero and allow IRQ to retrigger causing events to be509509+ * re-evaluated and re-sent.510510+ *511511+ * This structure is used for registering regulator IRQ notification helper.512512+ */513513+struct regulator_irq_desc {514514+ const char *name;515515+ int irq_flags;516516+ int fatal_cnt;517517+ int reread_ms;518518+ int irq_off_ms;519519+ bool skip_off;520520+ bool high_prio;521521+ void *data;522522+523523+ int (*die)(struct regulator_irq_data *rid);524524+ int (*map_event)(int irq, struct regulator_irq_data *rid,525525+ unsigned long *dev_mask);526526+ int (*renable)(struct regulator_irq_data *rid);527527+};528528+529529+/*530530+ * Return values for regulator IRQ helpers.531531+ */532532+enum {533533+ REGULATOR_ERROR_CLEARED,534534+ REGULATOR_FAILED_RETRY,535535+ REGULATOR_ERROR_ON,536536+};537537+449538/*450539 * struct coupling_desc451540 *···632477633478 /* time when this regulator was disabled last time */634479 ktime_t last_off;480480+ int cached_err;481481+ bool use_cached_err;482482+ spinlock_t err_lock;635483};636484637485struct regulator_dev *···649491650492int regulator_notifier_call_chain(struct regulator_dev *rdev,651493 unsigned long event, void *data);494494+void *devm_regulator_irq_helper(struct device *dev,495495+ const struct regulator_irq_desc *d, int irq,496496+ int irq_flags, int common_errs,497497+ int *per_rdev_errs, struct regulator_dev **rdev,498498+ int rdev_amount);499499+void *regulator_irq_helper(struct device *dev,500500+ const struct regulator_irq_desc *d, int irq,501501+ int irq_flags, int common_errs, int *per_rdev_errs,502502+ struct regulator_dev **rdev, int rdev_amount);503503+void regulator_irq_helper_cancel(void **handle);652504653505void *rdev_get_drvdata(struct regulator_dev *rdev);654506struct device *rdev_get_dev(struct regulator_dev *rdev);···708540int regulator_get_current_limit_regmap(struct regulator_dev *rdev);709541void *regulator_get_init_drvdata(struct regulator_init_data *reg_init_data);710542int regulator_set_ramp_delay_regmap(struct regulator_dev *rdev, int ramp_delay);543543+int regulator_sync_voltage_rdev(struct regulator_dev *rdev);711544712545/*713546 * Helper functions intended to be used by regulator drivers prior registering···719550720551int regulator_desc_list_voltage_linear(const struct regulator_desc *desc,721552 unsigned int selector);553553+554554+#ifdef CONFIG_REGULATOR555555+const char *rdev_get_name(struct regulator_dev *rdev);556556+#else557557+static inline const char *rdev_get_name(struct regulator_dev *rdev)558558+{559559+ return NULL;560560+}561561+#endif562562+722563#endif
+26
include/linux/regulator/machine.h
···8383 bool changeable;8484};85858686+#define REGULATOR_NOTIF_LIMIT_DISABLE -18787+#define REGULATOR_NOTIF_LIMIT_ENABLE -28888+struct notification_limit {8989+ int prot;9090+ int err;9191+ int warn;9292+};9393+8694/**8795 * struct regulation_constraints - regulator operating constraints.8896 *···108100 * @ilim_uA: Maximum input current.109101 * @system_load: Load that isn't captured by any consumer requests.110102 *103103+ * @over_curr_limits: Limits for acting on over current.104104+ * @over_voltage_limits: Limits for acting on over voltage.105105+ * @under_voltage_limits: Limits for acting on under voltage.106106+ * @temp_limits: Limits for acting on over temperature.107107+111108 * @max_spread: Max possible spread between coupled regulators112109 * @max_uV_step: Max possible step change in voltage113110 * @valid_modes_mask: Mask of modes which may be configured by consumers.···128115 * @soft_start: Enable soft start so that voltage ramps slowly.129116 * @pull_down: Enable pull down when regulator is disabled.130117 * @over_current_protection: Auto disable on over current event.118118+ *119119+ * @over_current_detection: Configure over current limits.120120+ * @over_voltage_detection: Configure over voltage limits.121121+ * @under_voltage_detection: Configure under voltage limits.122122+ * @over_temp_detection: Configure over temperature limits.131123 *132124 * @input_uV: Input voltage for regulator when supplied by another regulator.133125 *···190172 struct regulator_state state_disk;191173 struct regulator_state state_mem;192174 struct regulator_state state_standby;175175+ struct notification_limit over_curr_limits;176176+ struct notification_limit over_voltage_limits;177177+ struct notification_limit under_voltage_limits;178178+ struct notification_limit temp_limits;193179 suspend_state_t initial_state; /* suspend state to set at init */194180195181 /* mode to set on startup */···215193 unsigned soft_start:1; /* ramp voltage slowly */216194 unsigned pull_down:1; /* pull down resistor when regulator off */217195 unsigned over_current_protection:1; /* auto disable on over current */196196+ unsigned over_current_detection:1; /* notify on over current */197197+ unsigned over_voltage_detection:1; /* notify on over voltage */198198+ unsigned under_voltage_detection:1; /* notify on under voltage */199199+ unsigned over_temp_detection:1; /* notify on over temperature */218200};219201220202/**
···7788#define pr_fmt(fmt) "reboot: " fmt991010+#include <linux/atomic.h>1011#include <linux/ctype.h>1112#include <linux/export.h>1213#include <linux/kexec.h>···518517 schedule_work(&reboot_work);519518}520519EXPORT_SYMBOL_GPL(orderly_reboot);520520+521521+/**522522+ * hw_failure_emergency_poweroff_func - emergency poweroff work after a known delay523523+ * @work: work_struct associated with the emergency poweroff function524524+ *525525+ * This function is called in very critical situations to force526526+ * a kernel poweroff after a configurable timeout value.527527+ */528528+static void hw_failure_emergency_poweroff_func(struct work_struct *work)529529+{530530+ /*531531+ * We have reached here after the emergency shutdown waiting period has532532+ * expired. This means orderly_poweroff has not been able to shut off533533+ * the system for some reason.534534+ *535535+ * Try to shut down the system immediately using kernel_power_off536536+ * if populated537537+ */538538+ pr_emerg("Hardware protection timed-out. Trying forced poweroff\n");539539+ kernel_power_off();540540+541541+ /*542542+ * Worst of the worst case trigger emergency restart543543+ */544544+ pr_emerg("Hardware protection shutdown failed. Trying emergency restart\n");545545+ emergency_restart();546546+}547547+548548+static DECLARE_DELAYED_WORK(hw_failure_emergency_poweroff_work,549549+ hw_failure_emergency_poweroff_func);550550+551551+/**552552+ * hw_failure_emergency_poweroff - Trigger an emergency system poweroff553553+ *554554+ * This may be called from any critical situation to trigger a system shutdown555555+ * after a given period of time. If time is negative this is not scheduled.556556+ */557557+static void hw_failure_emergency_poweroff(int poweroff_delay_ms)558558+{559559+ if (poweroff_delay_ms <= 0)560560+ return;561561+ schedule_delayed_work(&hw_failure_emergency_poweroff_work,562562+ msecs_to_jiffies(poweroff_delay_ms));563563+}564564+565565+/**566566+ * hw_protection_shutdown - Trigger an emergency system poweroff567567+ *568568+ * @reason: Reason of emergency shutdown to be printed.569569+ * @ms_until_forced: Time to wait for orderly shutdown before tiggering a570570+ * forced shudown. Negative value disables the forced571571+ * shutdown.572572+ *573573+ * Initiate an emergency system shutdown in order to protect hardware from574574+ * further damage. Usage examples include a thermal protection or a voltage or575575+ * current regulator failures.576576+ * NOTE: The request is ignored if protection shutdown is already pending even577577+ * if the previous request has given a large timeout for forced shutdown.578578+ * Can be called from any context.579579+ */580580+void hw_protection_shutdown(const char *reason, int ms_until_forced)581581+{582582+ static atomic_t allow_proceed = ATOMIC_INIT(1);583583+584584+ pr_emerg("HARDWARE PROTECTION shutdown (%s)\n", reason);585585+586586+ /* Shutdown should be initiated only once. */587587+ if (!atomic_dec_and_test(&allow_proceed))588588+ return;589589+590590+ /*591591+ * Queue a backup emergency shutdown in the event of592592+ * orderly_poweroff failure593593+ */594594+ hw_failure_emergency_poweroff(ms_until_forced);595595+ orderly_poweroff(true);596596+}597597+EXPORT_SYMBOL_GPL(hw_protection_shutdown);521598522599static int __init reboot_setup(char *str)523600{