Select the types of activity you want to include in your feed.
Merge branches 'ib-firmware-mfd-6.16', 'ib-mfd-clocksource-pwm-6.16', 'ib-mfd-gpio-nvmem-6.16', 'ib-mfd-regulator-6.16' and 'ib-mfd-regulator-6.16-1' into ibs-for-mfd-merged
···44$id: http://devicetree.org/schemas/mfd/rohm,bd96801-pmic.yaml#55$schema: http://devicetree.org/meta-schemas/core.yaml#6677-title: ROHM BD96801 Scalable Power Management Integrated Circuit77+title: ROHM BD96801/BD96805 Scalable Power Management Integrated Circuit8899maintainers:1010 - Matti Vaittinen <matti.vaittinen@fi.rohmeurope.com>11111212description:1313- BD96801 is an automotive grade single-chip power management IC.1414- It integrates 4 buck converters and 3 LDOs with safety features like1313+ BD96801 and BD96805 are automotive grade, single-chip power management ICs.1414+ They both integrate 4 buck converters and 3 LDOs with safety features like1515 over-/under voltage and over current detection and a watchdog.16161717properties:1818 compatible:1919- const: rohm,bd968011919+ enum:2020+ - rohm,bd968012121+ - rohm,bd9680520222123 reg:2224 maxItems: 1
···11+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause22+%YAML 1.233+---44+$id: http://devicetree.org/schemas/mfd/rohm,bd96802-pmic.yaml#55+$schema: http://devicetree.org/meta-schemas/core.yaml#66+77+title: ROHM BD96802 / BD96806 Scalable Power Management Integrated Circuit88+99+maintainers:1010+ - Matti Vaittinen <matti.vaittinen@fi.rohmeurope.com>1111+1212+description: |1313+ BD96802Qxx-C and BD96806 are automotive grade configurable Power Management1414+ Integrated Circuits supporting Functional Safety features for application1515+ processors, SoCs and FPGAs1616+1717+properties:1818+ compatible:1919+ enum:2020+ - rohm,bd968022121+ - rohm,bd968062222+2323+ reg:2424+ maxItems: 12525+2626+ interrupts:2727+ description:2828+ The PMIC provides intb and errb IRQ lines. The errb IRQ line is used2929+ for fatal IRQs which will cause the PMIC to shut down power outputs.3030+ In many systems this will shut down the SoC contolling the PMIC and3131+ connecting/handling the errb can be omitted. However, there are cases3232+ where the SoC is not powered by the PMIC or has a short time backup3333+ energy to handle shutdown of critical hardware. In that case it may be3434+ useful to connect the errb and handle errb events.3535+ minItems: 13636+ maxItems: 23737+3838+ interrupt-names:3939+ minItems: 14040+ items:4141+ - enum: [intb, errb]4242+ - const: errb4343+4444+ regulators:4545+ $ref: ../regulator/rohm,bd96802-regulator.yaml4646+ description:4747+ List of child nodes that specify the regulators.4848+4949+required:5050+ - compatible5151+ - reg5252+ - interrupts5353+ - interrupt-names5454+ - regulators5555+5656+additionalProperties: false5757+5858+examples:5959+ - |6060+ #include <dt-bindings/interrupt-controller/irq.h>6161+ #include <dt-bindings/leds/common.h>6262+ i2c {6363+ #address-cells = <1>;6464+ #size-cells = <0>;6565+ pmic: pmic@62 {6666+ reg = <0x62>;6767+ compatible = "rohm,bd96802";6868+ interrupt-parent = <&gpio1>;6969+ interrupts = <29 IRQ_TYPE_LEVEL_LOW>, <6 IRQ_TYPE_LEVEL_LOW>;7070+ interrupt-names = "intb", "errb";7171+7272+ regulators {7373+ buck1 {7474+ regulator-name = "buck1";7575+ regulator-ramp-delay = <1250>;7676+ /* 0.5V min INITIAL - 150 mV tune */7777+ regulator-min-microvolt = <350000>;7878+ /* 3.3V + 150mV tune */7979+ regulator-max-microvolt = <3450000>;8080+8181+ /* These can be set only when PMIC is in STBY */8282+ rohm,initial-voltage-microvolt = <500000>;8383+ regulator-ov-error-microvolt = <230000>;8484+ regulator-uv-error-microvolt = <230000>;8585+ regulator-temp-protection-kelvin = <1>;8686+ regulator-temp-warn-kelvin = <0>;8787+ };8888+ buck2 {8989+ regulator-name = "buck2";9090+ regulator-min-microvolt = <350000>;9191+ regulator-max-microvolt = <3450000>;9292+9393+ rohm,initial-voltage-microvolt = <3000000>;9494+ regulator-ov-error-microvolt = <18000>;9595+ regulator-uv-error-microvolt = <18000>;9696+ regulator-temp-protection-kelvin = <1>;9797+ regulator-temp-warn-kelvin = <1>;9898+ };9999+ };100100+ };101101+ };
···11+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)22+%YAML 1.233+---44+$id: http://devicetree.org/schemas/nvmem/maxim,max77759-nvmem.yaml#55+$schema: http://devicetree.org/meta-schemas/core.yaml#66+77+title: Maxim Integrated MAX77759 Non Volatile Memory88+99+maintainers:1010+ - André Draszik <andre.draszik@linaro.org>1111+1212+description: |1313+ This module is part of the MAX77759 PMIC. For additional information, see1414+ Documentation/devicetree/bindings/mfd/maxim,max77759.yaml.1515+1616+ The MAX77759 is a PMIC integrating, amongst others, Non Volatile Memory1717+ (NVMEM) with 30 bytes of storage which can be used by software to store1818+ information or communicate with a boot loader.1919+2020+properties:2121+ compatible:2222+ const: maxim,max77759-nvmem2323+2424+ wp-gpios: false2525+2626+required:2727+ - compatible2828+2929+allOf:3030+ - $ref: nvmem.yaml#3131+3232+unevaluatedProperties: false
···11+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause22+%YAML 1.233+---44+$id: http://devicetree.org/schemas/regulator/rohm,bd96802-regulator.yaml#55+$schema: http://devicetree.org/meta-schemas/core.yaml#66+77+title: ROHM BD96802 Power Management Integrated Circuit regulators88+99+maintainers:1010+ - Matti Vaittinen <matti.vaittinen@fi.rohmeurope.com>1111+1212+description:1313+ This module is part of the ROHM BD96802 MFD device. For more details1414+ see Documentation/devicetree/bindings/mfd/rohm,bd96802-pmic.yaml.1515+1616+ The regulator controller is represented as a sub-node of the PMIC node1717+ on the device tree.1818+1919+ Regulator nodes should be named to buck1 and buck2.2020+2121+patternProperties:2222+ "^buck[1-2]$":2323+ type: object2424+ description:2525+ Properties for single BUCK regulator.2626+ $ref: regulator.yaml#2727+2828+ properties:2929+ rohm,initial-voltage-microvolt:3030+ description:3131+ Initial voltage for regulator. Voltage can be tuned +/-150 mV from3232+ this value. NOTE, This can be modified via I2C only when PMIC is in3333+ STBY state.3434+ minimum: 5000003535+ maximum: 33000003636+3737+ rohm,keep-on-stby:3838+ description:3939+ Keep the regulator powered when PMIC transitions to STBY state.4040+ type: boolean4141+4242+ unevaluatedProperties: false4343+4444+additionalProperties: false
···55 * Pascal Paillet <p.paillet@st.com> for STMicroelectronics.66 */7788+#include <linux/bitfield.h>89#include <linux/clk.h>910#include <linux/clockchips.h>1011#include <linux/interrupt.h>···2827 u32 psc;2928 struct device *dev;3029 struct clk *clk;3030+ u32 version;3131};32323333static struct stm32_lp_private*···4947 return 0;5048}51495252-static int stm32_clkevent_lp_set_timer(unsigned long evt,5353- struct clock_event_device *clkevt,5454- int is_periodic)5050+static int stm32mp25_clkevent_lp_set_evt(struct stm32_lp_private *priv, unsigned long evt)5551{5656- struct stm32_lp_private *priv = to_priv(clkevt);5252+ int ret;5353+ u32 val;57545555+ regmap_read(priv->reg, STM32_LPTIM_CR, &val);5656+ if (!FIELD_GET(STM32_LPTIM_ENABLE, val)) {5757+ /* Enable LPTIMER to be able to write into IER and ARR registers */5858+ regmap_write(priv->reg, STM32_LPTIM_CR, STM32_LPTIM_ENABLE);5959+ /*6060+ * After setting the ENABLE bit, a delay of two counter clock cycles is needed6161+ * before the LPTIM is actually enabled. For 32KHz rate, this makes approximately6262+ * 62.5 micro-seconds, round it up.6363+ */6464+ udelay(63);6565+ }6666+ /* set next event counter */6767+ regmap_write(priv->reg, STM32_LPTIM_ARR, evt);6868+ /* enable ARR interrupt */6969+ regmap_write(priv->reg, STM32_LPTIM_IER, STM32_LPTIM_ARRMIE);7070+7171+ /* Poll DIEROK and ARROK to ensure register access has completed */7272+ ret = regmap_read_poll_timeout_atomic(priv->reg, STM32_LPTIM_ISR, val,7373+ (val & STM32_LPTIM_DIEROK_ARROK) ==7474+ STM32_LPTIM_DIEROK_ARROK,7575+ 10, 500);7676+ if (ret) {7777+ dev_err(priv->dev, "access to LPTIM timed out\n");7878+ /* Disable LPTIMER */7979+ regmap_write(priv->reg, STM32_LPTIM_CR, 0);8080+ return ret;8181+ }8282+ /* Clear DIEROK and ARROK flags */8383+ regmap_write(priv->reg, STM32_LPTIM_ICR, STM32_LPTIM_DIEROKCF_ARROKCF);8484+8585+ return 0;8686+}8787+8888+static void stm32_clkevent_lp_set_evt(struct stm32_lp_private *priv, unsigned long evt)8989+{5890 /* disable LPTIMER to be able to write into IER register*/5991 regmap_write(priv->reg, STM32_LPTIM_CR, 0);6092 /* enable ARR interrupt */···9761 regmap_write(priv->reg, STM32_LPTIM_CR, STM32_LPTIM_ENABLE);9862 /* set next event counter */9963 regmap_write(priv->reg, STM32_LPTIM_ARR, evt);6464+}6565+6666+static int stm32_clkevent_lp_set_timer(unsigned long evt,6767+ struct clock_event_device *clkevt,6868+ int is_periodic)6969+{7070+ struct stm32_lp_private *priv = to_priv(clkevt);7171+ int ret;7272+7373+ if (priv->version == STM32_LPTIM_VERR_23) {7474+ ret = stm32mp25_clkevent_lp_set_evt(priv, evt);7575+ if (ret)7676+ return ret;7777+ } else {7878+ stm32_clkevent_lp_set_evt(priv, evt);7979+ }1008010181 /* start counter */10282 if (is_periodic)···228176 return -ENOMEM;229177230178 priv->reg = ddata->regmap;179179+ priv->version = ddata->version;231180 priv->clk = ddata->clk;232181 ret = clk_prepare_enable(priv->clk);233182 if (ret)
+13
drivers/gpio/Kconfig
···14631463 GPIO driver for MAX77650/77651 PMIC from Maxim Semiconductor.14641464 These chips have a single pin that can be configured as GPIO.1465146514661466+config GPIO_MAX7775914671467+ tristate "Maxim Integrated MAX77759 GPIO support"14681468+ depends on MFD_MAX7775914691469+ default MFD_MAX7775914701470+ select GPIOLIB_IRQCHIP14711471+ help14721472+ GPIO driver for MAX77759 PMIC from Maxim Integrated.14731473+ There are two GPIOs available on these chips in total, both of14741474+ which can also generate interrupts.14751475+14761476+ This driver can also be built as a module. If so, the module will be14771477+ called gpio-max77759.14781478+14661479config GPIO_PALMAS14671480 bool "TI PALMAS series PMICs GPIO"14681481 depends on MFD_PALMAS
···11+// SPDX-License-Identifier: GPL-2.0-only22+//33+// Copyright 2020 Google Inc44+// Copyright 2025 Linaro Ltd.55+//66+// GPIO driver for Maxim MAX7775977+88+#include <linux/dev_printk.h>99+#include <linux/device.h>1010+#include <linux/device/driver.h>1111+#include <linux/gpio/driver.h>1212+#include <linux/interrupt.h>1313+#include <linux/irq.h>1414+#include <linux/irqreturn.h>1515+#include <linux/lockdep.h>1616+#include <linux/mfd/max77759.h>1717+#include <linux/mod_devicetable.h>1818+#include <linux/module.h>1919+#include <linux/overflow.h>2020+#include <linux/platform_device.h>2121+#include <linux/regmap.h>2222+#include <linux/seq_file.h>2323+2424+#define MAX77759_N_GPIOS ARRAY_SIZE(max77759_gpio_line_names)2525+static const char * const max77759_gpio_line_names[] = { "GPIO5", "GPIO6" };2626+2727+struct max77759_gpio_chip {2828+ struct regmap *map;2929+ struct max77759 *max77759;3030+ struct gpio_chip gc;3131+ struct mutex maxq_lock; /* protect MaxQ r/m/w operations */3232+3333+ struct mutex irq_lock; /* protect irq bus */3434+ int irq_mask;3535+ int irq_mask_changed;3636+ int irq_trig;3737+ int irq_trig_changed;3838+};3939+4040+#define MAX77759_GPIOx_TRIGGER(offs, val) (((val) & 1) << (offs))4141+#define MAX77759_GPIOx_TRIGGER_MASK(offs) MAX77759_GPIOx_TRIGGER(offs, ~0)4242+enum max77759_trigger_gpio_type {4343+ MAX77759_GPIO_TRIGGER_RISING = 0,4444+ MAX77759_GPIO_TRIGGER_FALLING = 14545+};4646+4747+#define MAX77759_GPIOx_DIR(offs, dir) (((dir) & 1) << (2 + (3 * (offs))))4848+#define MAX77759_GPIOx_DIR_MASK(offs) MAX77759_GPIOx_DIR(offs, ~0)4949+enum max77759_control_gpio_dir {5050+ MAX77759_GPIO_DIR_IN = 0,5151+ MAX77759_GPIO_DIR_OUT = 15252+};5353+5454+#define MAX77759_GPIOx_OUTVAL(offs, val) (((val) & 1) << (3 + (3 * (offs))))5555+#define MAX77759_GPIOx_OUTVAL_MASK(offs) MAX77759_GPIOx_OUTVAL(offs, ~0)5656+5757+#define MAX77759_GPIOx_INVAL_MASK(offs) (BIT(4) << (3 * (offs)))5858+5959+static int max77759_gpio_maxq_gpio_trigger_read(struct max77759_gpio_chip *chip)6060+{6161+ DEFINE_FLEX(struct max77759_maxq_command, cmd, cmd, length, 1);6262+ DEFINE_FLEX(struct max77759_maxq_response, rsp, rsp, length, 2);6363+ int ret;6464+6565+ cmd->cmd[0] = MAX77759_MAXQ_OPCODE_GPIO_TRIGGER_READ;6666+6767+ ret = max77759_maxq_command(chip->max77759, cmd, rsp);6868+ if (ret < 0)6969+ return ret;7070+7171+ return rsp->rsp[1];7272+}7373+7474+static int max77759_gpio_maxq_gpio_trigger_write(struct max77759_gpio_chip *chip,7575+ u8 trigger)7676+{7777+ DEFINE_FLEX(struct max77759_maxq_command, cmd, cmd, length, 2);7878+7979+ cmd->cmd[0] = MAX77759_MAXQ_OPCODE_GPIO_TRIGGER_WRITE;8080+ cmd->cmd[1] = trigger;8181+8282+ return max77759_maxq_command(chip->max77759, cmd, NULL);8383+}8484+8585+static int max77759_gpio_maxq_gpio_control_read(struct max77759_gpio_chip *chip)8686+{8787+ DEFINE_FLEX(struct max77759_maxq_command, cmd, cmd, length, 1);8888+ DEFINE_FLEX(struct max77759_maxq_response, rsp, rsp, length, 2);8989+ int ret;9090+9191+ cmd->cmd[0] = MAX77759_MAXQ_OPCODE_GPIO_CONTROL_READ;9292+9393+ ret = max77759_maxq_command(chip->max77759, cmd, rsp);9494+ if (ret < 0)9595+ return ret;9696+9797+ return rsp->rsp[1];9898+}9999+100100+static int max77759_gpio_maxq_gpio_control_write(struct max77759_gpio_chip *chip,101101+ u8 ctrl)102102+{103103+ DEFINE_FLEX(struct max77759_maxq_command, cmd, cmd, length, 2);104104+105105+ cmd->cmd[0] = MAX77759_MAXQ_OPCODE_GPIO_CONTROL_WRITE;106106+ cmd->cmd[1] = ctrl;107107+108108+ return max77759_maxq_command(chip->max77759, cmd, NULL);109109+}110110+111111+static int112112+max77759_gpio_direction_from_control(int ctrl, unsigned int offset)113113+{114114+ enum max77759_control_gpio_dir dir;115115+116116+ dir = !!(ctrl & MAX77759_GPIOx_DIR_MASK(offset));117117+ return ((dir == MAX77759_GPIO_DIR_OUT)118118+ ? GPIO_LINE_DIRECTION_OUT119119+ : GPIO_LINE_DIRECTION_IN);120120+}121121+122122+static int max77759_gpio_get_direction(struct gpio_chip *gc,123123+ unsigned int offset)124124+{125125+ struct max77759_gpio_chip *chip = gpiochip_get_data(gc);126126+ int ctrl;127127+128128+ ctrl = max77759_gpio_maxq_gpio_control_read(chip);129129+ if (ctrl < 0)130130+ return ctrl;131131+132132+ return max77759_gpio_direction_from_control(ctrl, offset);133133+}134134+135135+static int max77759_gpio_direction_helper(struct gpio_chip *gc,136136+ unsigned int offset,137137+ enum max77759_control_gpio_dir dir,138138+ int value)139139+{140140+ struct max77759_gpio_chip *chip = gpiochip_get_data(gc);141141+ int ctrl, new_ctrl;142142+143143+ guard(mutex)(&chip->maxq_lock);144144+145145+ ctrl = max77759_gpio_maxq_gpio_control_read(chip);146146+ if (ctrl < 0)147147+ return ctrl;148148+149149+ new_ctrl = ctrl & ~MAX77759_GPIOx_DIR_MASK(offset);150150+ new_ctrl |= MAX77759_GPIOx_DIR(offset, dir);151151+152152+ if (dir == MAX77759_GPIO_DIR_OUT) {153153+ new_ctrl &= ~MAX77759_GPIOx_OUTVAL_MASK(offset);154154+ new_ctrl |= MAX77759_GPIOx_OUTVAL(offset, value);155155+ }156156+157157+ if (new_ctrl == ctrl)158158+ return 0;159159+160160+ return max77759_gpio_maxq_gpio_control_write(chip, new_ctrl);161161+}162162+163163+static int max77759_gpio_direction_input(struct gpio_chip *gc,164164+ unsigned int offset)165165+{166166+ return max77759_gpio_direction_helper(gc, offset,167167+ MAX77759_GPIO_DIR_IN, -1);168168+}169169+170170+static int max77759_gpio_direction_output(struct gpio_chip *gc,171171+ unsigned int offset, int value)172172+{173173+ return max77759_gpio_direction_helper(gc, offset,174174+ MAX77759_GPIO_DIR_OUT, value);175175+}176176+177177+static int max77759_gpio_get_value(struct gpio_chip *gc, unsigned int offset)178178+{179179+ struct max77759_gpio_chip *chip = gpiochip_get_data(gc);180180+ int ctrl, mask;181181+182182+ ctrl = max77759_gpio_maxq_gpio_control_read(chip);183183+ if (ctrl < 0)184184+ return ctrl;185185+186186+ /*187187+ * The input status bit doesn't reflect the pin state when the GPIO is188188+ * configured as an output. Check the direction, and inspect the input189189+ * or output bit accordingly.190190+ */191191+ mask = ((max77759_gpio_direction_from_control(ctrl, offset)192192+ == GPIO_LINE_DIRECTION_IN)193193+ ? MAX77759_GPIOx_INVAL_MASK(offset)194194+ : MAX77759_GPIOx_OUTVAL_MASK(offset));195195+196196+ return !!(ctrl & mask);197197+}198198+199199+static int max77759_gpio_set_value(struct gpio_chip *gc,200200+ unsigned int offset, int value)201201+{202202+ struct max77759_gpio_chip *chip = gpiochip_get_data(gc);203203+ int ctrl, new_ctrl;204204+205205+ guard(mutex)(&chip->maxq_lock);206206+207207+ ctrl = max77759_gpio_maxq_gpio_control_read(chip);208208+ if (ctrl < 0)209209+ return ctrl;210210+211211+ new_ctrl = ctrl & ~MAX77759_GPIOx_OUTVAL_MASK(offset);212212+ new_ctrl |= MAX77759_GPIOx_OUTVAL(offset, value);213213+214214+ if (new_ctrl == ctrl)215215+ return 0;216216+217217+ return max77759_gpio_maxq_gpio_control_write(chip, new_ctrl);218218+}219219+220220+static void max77759_gpio_irq_mask(struct irq_data *d)221221+{222222+ struct gpio_chip *gc = irq_data_get_irq_chip_data(d);223223+ struct max77759_gpio_chip *chip = gpiochip_get_data(gc);224224+ irq_hw_number_t hwirq = irqd_to_hwirq(d);225225+226226+ chip->irq_mask &= ~MAX77759_MAXQ_REG_UIC_INT1_GPIOxI_MASK(hwirq);227227+ chip->irq_mask |= MAX77759_MAXQ_REG_UIC_INT1_GPIOxI(hwirq, 1);228228+ chip->irq_mask_changed |= MAX77759_MAXQ_REG_UIC_INT1_GPIOxI(hwirq, 1);229229+230230+ gpiochip_disable_irq(gc, hwirq);231231+}232232+233233+static void max77759_gpio_irq_unmask(struct irq_data *d)234234+{235235+ struct gpio_chip *gc = irq_data_get_irq_chip_data(d);236236+ struct max77759_gpio_chip *chip = gpiochip_get_data(gc);237237+ irq_hw_number_t hwirq = irqd_to_hwirq(d);238238+239239+ gpiochip_enable_irq(gc, hwirq);240240+241241+ chip->irq_mask &= ~MAX77759_MAXQ_REG_UIC_INT1_GPIOxI_MASK(hwirq);242242+ chip->irq_mask |= MAX77759_MAXQ_REG_UIC_INT1_GPIOxI(hwirq, 0);243243+ chip->irq_mask_changed |= MAX77759_MAXQ_REG_UIC_INT1_GPIOxI(hwirq, 1);244244+}245245+246246+static int max77759_gpio_set_irq_type(struct irq_data *d, unsigned int type)247247+{248248+ struct gpio_chip *gc = irq_data_get_irq_chip_data(d);249249+ struct max77759_gpio_chip *chip = gpiochip_get_data(gc);250250+ irq_hw_number_t hwirq = irqd_to_hwirq(d);251251+252252+ chip->irq_trig &= ~MAX77759_GPIOx_TRIGGER_MASK(hwirq);253253+ switch (type) {254254+ case IRQ_TYPE_EDGE_RISING:255255+ chip->irq_trig |= MAX77759_GPIOx_TRIGGER(hwirq,256256+ MAX77759_GPIO_TRIGGER_RISING);257257+ break;258258+259259+ case IRQ_TYPE_EDGE_FALLING:260260+ chip->irq_trig |= MAX77759_GPIOx_TRIGGER(hwirq,261261+ MAX77759_GPIO_TRIGGER_FALLING);262262+ break;263263+264264+ default:265265+ return -EINVAL;266266+ }267267+268268+ chip->irq_trig_changed |= MAX77759_GPIOx_TRIGGER(hwirq, 1);269269+270270+ return 0;271271+}272272+273273+static void max77759_gpio_bus_lock(struct irq_data *d)274274+{275275+ struct gpio_chip *gc = irq_data_get_irq_chip_data(d);276276+ struct max77759_gpio_chip *chip = gpiochip_get_data(gc);277277+278278+ mutex_lock(&chip->irq_lock);279279+}280280+281281+static int max77759_gpio_bus_sync_unlock_helper(struct gpio_chip *gc,282282+ struct max77759_gpio_chip *chip)283283+ __must_hold(&chip->maxq_lock)284284+{285285+ int ctrl, trigger, new_trigger, new_ctrl;286286+ unsigned long irq_trig_changed;287287+ int offset;288288+ int ret;289289+290290+ lockdep_assert_held(&chip->maxq_lock);291291+292292+ ctrl = max77759_gpio_maxq_gpio_control_read(chip);293293+ trigger = max77759_gpio_maxq_gpio_trigger_read(chip);294294+ if (ctrl < 0 || trigger < 0) {295295+ dev_err(gc->parent, "failed to read current state: %d / %d\n",296296+ ctrl, trigger);297297+ return (ctrl < 0) ? ctrl : trigger;298298+ }299299+300300+ new_trigger = trigger & ~chip->irq_trig_changed;301301+ new_trigger |= (chip->irq_trig & chip->irq_trig_changed);302302+303303+ /* change GPIO direction if required */304304+ new_ctrl = ctrl;305305+ irq_trig_changed = chip->irq_trig_changed;306306+ for_each_set_bit(offset, &irq_trig_changed, MAX77759_N_GPIOS) {307307+ new_ctrl &= ~MAX77759_GPIOx_DIR_MASK(offset);308308+ new_ctrl |= MAX77759_GPIOx_DIR(offset, MAX77759_GPIO_DIR_IN);309309+ }310310+311311+ if (new_trigger != trigger) {312312+ ret = max77759_gpio_maxq_gpio_trigger_write(chip, new_trigger);313313+ if (ret) {314314+ dev_err(gc->parent,315315+ "failed to write new trigger: %d\n", ret);316316+ return ret;317317+ }318318+ }319319+320320+ if (new_ctrl != ctrl) {321321+ ret = max77759_gpio_maxq_gpio_control_write(chip, new_ctrl);322322+ if (ret) {323323+ dev_err(gc->parent,324324+ "failed to write new control: %d\n", ret);325325+ return ret;326326+ }327327+ }328328+329329+ chip->irq_trig_changed = 0;330330+331331+ return 0;332332+}333333+334334+static void max77759_gpio_bus_sync_unlock(struct irq_data *d)335335+{336336+ struct gpio_chip *gc = irq_data_get_irq_chip_data(d);337337+ struct max77759_gpio_chip *chip = gpiochip_get_data(gc);338338+ int ret;339339+340340+ scoped_guard(mutex, &chip->maxq_lock) {341341+ ret = max77759_gpio_bus_sync_unlock_helper(gc, chip);342342+ if (ret)343343+ goto out_unlock;344344+ }345345+346346+ ret = regmap_update_bits(chip->map,347347+ MAX77759_MAXQ_REG_UIC_INT1_M,348348+ chip->irq_mask_changed, chip->irq_mask);349349+ if (ret) {350350+ dev_err(gc->parent,351351+ "failed to update UIC_INT1 irq mask: %d\n", ret);352352+ goto out_unlock;353353+ }354354+355355+ chip->irq_mask_changed = 0;356356+357357+out_unlock:358358+ mutex_unlock(&chip->irq_lock);359359+}360360+361361+static void max77759_gpio_irq_print_chip(struct irq_data *d, struct seq_file *p)362362+{363363+ struct gpio_chip *gc = irq_data_get_irq_chip_data(d);364364+365365+ seq_puts(p, dev_name(gc->parent));366366+}367367+368368+static const struct irq_chip max77759_gpio_irq_chip = {369369+ .irq_mask = max77759_gpio_irq_mask,370370+ .irq_unmask = max77759_gpio_irq_unmask,371371+ .irq_set_type = max77759_gpio_set_irq_type,372372+ .irq_bus_lock = max77759_gpio_bus_lock,373373+ .irq_bus_sync_unlock = max77759_gpio_bus_sync_unlock,374374+ .irq_print_chip = max77759_gpio_irq_print_chip,375375+ .flags = IRQCHIP_IMMUTABLE,376376+ GPIOCHIP_IRQ_RESOURCE_HELPERS,377377+};378378+379379+static irqreturn_t max77759_gpio_irqhandler(int irq, void *data)380380+{381381+ struct max77759_gpio_chip *chip = data;382382+ struct gpio_chip *gc = &chip->gc;383383+ bool handled = false;384384+385385+ /* iterate until no interrupt is pending */386386+ while (true) {387387+ unsigned int uic_int1;388388+ int ret;389389+ unsigned long pending;390390+ int offset;391391+392392+ ret = regmap_read(chip->map, MAX77759_MAXQ_REG_UIC_INT1,393393+ &uic_int1);394394+ if (ret < 0) {395395+ dev_err_ratelimited(gc->parent,396396+ "failed to read IRQ status: %d\n",397397+ ret);398398+ /*399399+ * If !handled, we have looped not even once, which400400+ * means we should return IRQ_NONE in that case (and401401+ * of course IRQ_HANDLED otherwise).402402+ */403403+ return IRQ_RETVAL(handled);404404+ }405405+406406+ pending = uic_int1;407407+ pending &= (MAX77759_MAXQ_REG_UIC_INT1_GPIO6I408408+ | MAX77759_MAXQ_REG_UIC_INT1_GPIO5I);409409+ if (!pending)410410+ break;411411+412412+ for_each_set_bit(offset, &pending, MAX77759_N_GPIOS) {413413+ /*414414+ * ACK interrupt by writing 1 to bit 'offset', all415415+ * others need to be written as 0. This needs to be416416+ * done unconditionally hence regmap_set_bits() is417417+ * inappropriate here.418418+ */419419+ regmap_write(chip->map, MAX77759_MAXQ_REG_UIC_INT1,420420+ BIT(offset));421421+422422+ handle_nested_irq(irq_find_mapping(gc->irq.domain,423423+ offset));424424+425425+ handled = true;426426+ }427427+ }428428+429429+ return IRQ_RETVAL(handled);430430+}431431+432432+static int max77759_gpio_probe(struct platform_device *pdev)433433+{434434+ struct max77759_gpio_chip *chip;435435+ int irq;436436+ struct gpio_irq_chip *girq;437437+ int ret;438438+ unsigned long irq_flags;439439+ struct irq_data *irqd;440440+441441+ chip = devm_kzalloc(&pdev->dev, sizeof(*chip), GFP_KERNEL);442442+ if (!chip)443443+ return -ENOMEM;444444+445445+ chip->map = dev_get_regmap(pdev->dev.parent, "maxq");446446+ if (!chip->map)447447+ return dev_err_probe(&pdev->dev, -ENODEV, "Missing regmap\n");448448+449449+ irq = platform_get_irq_byname(pdev, "GPI");450450+ if (irq < 0)451451+ return dev_err_probe(&pdev->dev, irq, "Failed to get IRQ\n");452452+453453+ chip->max77759 = dev_get_drvdata(pdev->dev.parent);454454+ ret = devm_mutex_init(&pdev->dev, &chip->maxq_lock);455455+ if (ret)456456+ return ret;457457+ ret = devm_mutex_init(&pdev->dev, &chip->irq_lock);458458+ if (ret)459459+ return ret;460460+461461+ chip->gc.base = -1;462462+ chip->gc.label = dev_name(&pdev->dev);463463+ chip->gc.parent = &pdev->dev;464464+ chip->gc.can_sleep = true;465465+466466+ chip->gc.names = max77759_gpio_line_names;467467+ chip->gc.ngpio = MAX77759_N_GPIOS;468468+ chip->gc.get_direction = max77759_gpio_get_direction;469469+ chip->gc.direction_input = max77759_gpio_direction_input;470470+ chip->gc.direction_output = max77759_gpio_direction_output;471471+ chip->gc.get = max77759_gpio_get_value;472472+ chip->gc.set_rv = max77759_gpio_set_value;473473+474474+ girq = &chip->gc.irq;475475+ gpio_irq_chip_set_chip(girq, &max77759_gpio_irq_chip);476476+ /* This will let us handle the parent IRQ in the driver */477477+ girq->parent_handler = NULL;478478+ girq->num_parents = 0;479479+ girq->parents = NULL;480480+ girq->default_type = IRQ_TYPE_NONE;481481+ girq->handler = handle_simple_irq;482482+ girq->threaded = true;483483+484484+ ret = devm_gpiochip_add_data(&pdev->dev, &chip->gc, chip);485485+ if (ret < 0)486486+ return dev_err_probe(&pdev->dev, ret,487487+ "Failed to add GPIO chip\n");488488+489489+ irq_flags = IRQF_ONESHOT | IRQF_SHARED;490490+ irqd = irq_get_irq_data(irq);491491+ if (irqd)492492+ irq_flags |= irqd_get_trigger_type(irqd);493493+494494+ ret = devm_request_threaded_irq(&pdev->dev, irq, NULL,495495+ max77759_gpio_irqhandler, irq_flags,496496+ dev_name(&pdev->dev), chip);497497+ if (ret < 0)498498+ return dev_err_probe(&pdev->dev, ret,499499+ "Failed to request IRQ\n");500500+501501+ return ret;502502+}503503+504504+static const struct of_device_id max77759_gpio_of_id[] = {505505+ { .compatible = "maxim,max77759-gpio", },506506+ { }507507+};508508+MODULE_DEVICE_TABLE(of, max77759_gpio_of_id);509509+510510+static const struct platform_device_id max77759_gpio_platform_id[] = {511511+ { "max77759-gpio", },512512+ { }513513+};514514+MODULE_DEVICE_TABLE(platform, max77759_gpio_platform_id);515515+516516+static struct platform_driver max77759_gpio_driver = {517517+ .driver = {518518+ .name = "max77759-gpio",519519+ .probe_type = PROBE_PREFER_ASYNCHRONOUS,520520+ .of_match_table = max77759_gpio_of_id,521521+ },522522+ .probe = max77759_gpio_probe,523523+ .id_table = max77759_gpio_platform_id,524524+};525525+526526+module_platform_driver(max77759_gpio_driver);527527+528528+MODULE_AUTHOR("André Draszik <andre.draszik@linaro.org>");529529+MODULE_DESCRIPTION("GPIO driver for Maxim MAX77759");530530+MODULE_LICENSE("GPL");
+20
drivers/mfd/Kconfig
···943943 drivers must be enabled in order to use each functionality of the944944 device.945945946946+config MFD_MAX77759947947+ tristate "Maxim Integrated MAX77759 PMIC"948948+ depends on I2C949949+ depends on OF950950+ select IRQ_DOMAIN951951+ select MFD_CORE952952+ select REGMAP_I2C953953+ select REGMAP_IRQ954954+ help955955+ Say yes here to add support for Maxim Integrated MAX77759.956956+ This is a companion Power Management IC for USB Type-C applications957957+ with Battery Charger, Fuel Gauge, temperature sensors, USB Type-C958958+ Port Controller (TCPC), NVMEM, and additional GPIO interfaces.959959+ This driver provides common support for accessing the device;960960+ additional drivers must be enabled in order to use the functionality961961+ of the device.962962+963963+ To compile this driver as a module, choose M here: the module will be964964+ called max77759.965965+946966config MFD_MAX77843947967 bool "Maxim Semiconductor MAX77843 PMIC Support"948968 depends on I2C=y
···1717#include <linux/regmap.h>1818#include <linux/slab.h>19192020+/* Under primary I2C address: */2121+#define BCM590XX_REG_PMUID 0x1e2222+2323+#define BCM590XX_REG_PMUREV 0x1f2424+#define BCM590XX_PMUREV_DIG_MASK 0xF2525+#define BCM590XX_PMUREV_DIG_SHIFT 02626+#define BCM590XX_PMUREV_ANA_MASK 0xF02727+#define BCM590XX_PMUREV_ANA_SHIFT 42828+2029static const struct mfd_cell bcm590xx_devs[] = {2130 {2231 .name = "bcm590xx-vregs",···4637 .cache_type = REGCACHE_MAPLE,4738};48394040+/* Map PMU ID value to model name string */4141+static const char * const bcm590xx_names[] = {4242+ [BCM590XX_PMUID_BCM59054] = "BCM59054",4343+ [BCM590XX_PMUID_BCM59056] = "BCM59056",4444+};4545+4646+static int bcm590xx_parse_version(struct bcm590xx *bcm590xx)4747+{4848+ unsigned int id, rev;4949+ int ret;5050+5151+ /* Get PMU ID and verify that it matches compatible */5252+ ret = regmap_read(bcm590xx->regmap_pri, BCM590XX_REG_PMUID, &id);5353+ if (ret) {5454+ dev_err(bcm590xx->dev, "failed to read PMU ID: %d\n", ret);5555+ return ret;5656+ }5757+5858+ if (id != bcm590xx->pmu_id) {5959+ dev_err(bcm590xx->dev, "Incorrect ID for %s: expected %x, got %x.\n",6060+ bcm590xx_names[bcm590xx->pmu_id], bcm590xx->pmu_id, id);6161+ return -ENODEV;6262+ }6363+6464+ /* Get PMU revision and store it in the info struct */6565+ ret = regmap_read(bcm590xx->regmap_pri, BCM590XX_REG_PMUREV, &rev);6666+ if (ret) {6767+ dev_err(bcm590xx->dev, "failed to read PMU revision: %d\n", ret);6868+ return ret;6969+ }7070+7171+ bcm590xx->rev_digital = (rev & BCM590XX_PMUREV_DIG_MASK) >> BCM590XX_PMUREV_DIG_SHIFT;7272+7373+ bcm590xx->rev_analog = (rev & BCM590XX_PMUREV_ANA_MASK) >> BCM590XX_PMUREV_ANA_SHIFT;7474+7575+ dev_dbg(bcm590xx->dev, "PMU ID 0x%x (%s), revision: digital %d, analog %d",7676+ id, bcm590xx_names[id], bcm590xx->rev_digital, bcm590xx->rev_analog);7777+7878+ return 0;7979+}8080+4981static int bcm590xx_i2c_probe(struct i2c_client *i2c_pri)5082{5183 struct bcm590xx *bcm590xx;···9949 i2c_set_clientdata(i2c_pri, bcm590xx);10050 bcm590xx->dev = &i2c_pri->dev;10151 bcm590xx->i2c_pri = i2c_pri;5252+5353+ bcm590xx->pmu_id = (uintptr_t) of_device_get_match_data(bcm590xx->dev);1025410355 bcm590xx->regmap_pri = devm_regmap_init_i2c(i2c_pri,10456 &bcm590xx_regmap_config_pri);···12876 goto err;12977 }130787979+ ret = bcm590xx_parse_version(bcm590xx);8080+ if (ret)8181+ goto err;8282+13183 ret = devm_mfd_add_devices(&i2c_pri->dev, -1, bcm590xx_devs,13284 ARRAY_SIZE(bcm590xx_devs), NULL, 0, NULL);13385 if (ret < 0) {···14791}1489214993static const struct of_device_id bcm590xx_of_match[] = {150150- { .compatible = "brcm,bcm59056" },9494+ {9595+ .compatible = "brcm,bcm59054",9696+ .data = (void *)BCM590XX_PMUID_BCM59054,9797+ },9898+ {9999+ .compatible = "brcm,bcm59056",100100+ .data = (void *)BCM590XX_PMUID_BCM59056,101101+ },151102 { }152103};153104MODULE_DEVICE_TABLE(of, bcm590xx_of_match);154105155106static const struct i2c_device_id bcm590xx_i2c_id[] = {107107+ { "bcm59054" },156108 { "bcm59056" },157109 { }158110};
+690
drivers/mfd/max77759.c
···11+// SPDX-License-Identifier: GPL-2.0-only22+/*33+ * Copyright 2020 Google Inc44+ * Copyright 2025 Linaro Ltd.55+ *66+ * Core driver for Maxim MAX77759 companion PMIC for USB Type-C77+ */88+99+#include <linux/array_size.h>1010+#include <linux/bitfield.h>1111+#include <linux/bits.h>1212+#include <linux/cleanup.h>1313+#include <linux/completion.h>1414+#include <linux/dev_printk.h>1515+#include <linux/device.h>1616+#include <linux/err.h>1717+#include <linux/i2c.h>1818+#include <linux/init.h>1919+#include <linux/interrupt.h>2020+#include <linux/irq.h>2121+#include <linux/jiffies.h>2222+#include <linux/mfd/core.h>2323+#include <linux/mfd/max77759.h>2424+#include <linux/mod_devicetable.h>2525+#include <linux/module.h>2626+#include <linux/mutex.h>2727+#include <linux/of.h>2828+#include <linux/overflow.h>2929+#include <linux/regmap.h>3030+3131+/* Chip ID as per MAX77759_PMIC_REG_PMIC_ID */3232+enum {3333+ MAX77759_CHIP_ID = 59,3434+};3535+3636+enum max77759_i2c_subdev_id {3737+ /*3838+ * These are arbitrary and simply used to match struct3939+ * max77759_i2c_subdev entries to the regmap pointers in struct4040+ * max77759 during probe().4141+ */4242+ MAX77759_I2C_SUBDEV_ID_MAXQ,4343+ MAX77759_I2C_SUBDEV_ID_CHARGER,4444+};4545+4646+struct max77759_i2c_subdev {4747+ enum max77759_i2c_subdev_id id;4848+ const struct regmap_config *cfg;4949+ u16 i2c_address;5050+};5151+5252+static const struct regmap_range max77759_top_registers[] = {5353+ regmap_reg_range(0x00, 0x02), /* PMIC_ID / PMIC_REVISION / OTP_REVISION */5454+ regmap_reg_range(0x22, 0x24), /* INTSRC / INTSRCMASK / TOPSYS_INT */5555+ regmap_reg_range(0x26, 0x26), /* TOPSYS_INT_MASK */5656+ regmap_reg_range(0x40, 0x40), /* I2C_CNFG */5757+ regmap_reg_range(0x50, 0x51), /* SWRESET / CONTROL_FG */5858+};5959+6060+static const struct regmap_range max77759_top_ro_registers[] = {6161+ regmap_reg_range(0x00, 0x02),6262+ regmap_reg_range(0x22, 0x22),6363+};6464+6565+static const struct regmap_range max77759_top_volatile_registers[] = {6666+ regmap_reg_range(0x22, 0x22),6767+ regmap_reg_range(0x24, 0x24),6868+};6969+7070+static const struct regmap_access_table max77759_top_wr_table = {7171+ .yes_ranges = max77759_top_registers,7272+ .n_yes_ranges = ARRAY_SIZE(max77759_top_registers),7373+ .no_ranges = max77759_top_ro_registers,7474+ .n_no_ranges = ARRAY_SIZE(max77759_top_ro_registers),7575+};7676+7777+static const struct regmap_access_table max77759_top_rd_table = {7878+ .yes_ranges = max77759_top_registers,7979+ .n_yes_ranges = ARRAY_SIZE(max77759_top_registers),8080+};8181+8282+static const struct regmap_access_table max77759_top_volatile_table = {8383+ .yes_ranges = max77759_top_volatile_registers,8484+ .n_yes_ranges = ARRAY_SIZE(max77759_top_volatile_registers),8585+};8686+8787+static const struct regmap_config max77759_regmap_config_top = {8888+ .name = "top",8989+ .reg_bits = 8,9090+ .val_bits = 8,9191+ .max_register = MAX77759_PMIC_REG_CONTROL_FG,9292+ .wr_table = &max77759_top_wr_table,9393+ .rd_table = &max77759_top_rd_table,9494+ .volatile_table = &max77759_top_volatile_table,9595+ .num_reg_defaults_raw = MAX77759_PMIC_REG_CONTROL_FG + 1,9696+ .cache_type = REGCACHE_FLAT,9797+};9898+9999+static const struct regmap_range max77759_maxq_registers[] = {100100+ regmap_reg_range(0x60, 0x73), /* Device ID, Rev, INTx, STATUSx, MASKx */101101+ regmap_reg_range(0x81, 0xa1), /* AP_DATAOUTx */102102+ regmap_reg_range(0xb1, 0xd1), /* AP_DATAINx */103103+ regmap_reg_range(0xe0, 0xe0), /* UIC_SWRST */104104+};105105+106106+static const struct regmap_range max77759_maxq_ro_registers[] = {107107+ regmap_reg_range(0x60, 0x63), /* Device ID, Rev */108108+ regmap_reg_range(0x68, 0x6f), /* STATUSx */109109+ regmap_reg_range(0xb1, 0xd1),110110+};111111+112112+static const struct regmap_range max77759_maxq_volatile_registers[] = {113113+ regmap_reg_range(0x64, 0x6f), /* INTx, STATUSx */114114+ regmap_reg_range(0xb1, 0xd1),115115+ regmap_reg_range(0xe0, 0xe0),116116+};117117+118118+static const struct regmap_access_table max77759_maxq_wr_table = {119119+ .yes_ranges = max77759_maxq_registers,120120+ .n_yes_ranges = ARRAY_SIZE(max77759_maxq_registers),121121+ .no_ranges = max77759_maxq_ro_registers,122122+ .n_no_ranges = ARRAY_SIZE(max77759_maxq_ro_registers),123123+};124124+125125+static const struct regmap_access_table max77759_maxq_rd_table = {126126+ .yes_ranges = max77759_maxq_registers,127127+ .n_yes_ranges = ARRAY_SIZE(max77759_maxq_registers),128128+};129129+130130+static const struct regmap_access_table max77759_maxq_volatile_table = {131131+ .yes_ranges = max77759_maxq_volatile_registers,132132+ .n_yes_ranges = ARRAY_SIZE(max77759_maxq_volatile_registers),133133+};134134+135135+static const struct regmap_config max77759_regmap_config_maxq = {136136+ .name = "maxq",137137+ .reg_bits = 8,138138+ .val_bits = 8,139139+ .max_register = MAX77759_MAXQ_REG_UIC_SWRST,140140+ .wr_table = &max77759_maxq_wr_table,141141+ .rd_table = &max77759_maxq_rd_table,142142+ .volatile_table = &max77759_maxq_volatile_table,143143+ .num_reg_defaults_raw = MAX77759_MAXQ_REG_UIC_SWRST + 1,144144+ .cache_type = REGCACHE_FLAT,145145+};146146+147147+static const struct regmap_range max77759_charger_registers[] = {148148+ regmap_reg_range(0xb0, 0xcc),149149+};150150+151151+static const struct regmap_range max77759_charger_ro_registers[] = {152152+ regmap_reg_range(0xb4, 0xb8), /* INT_OK, DETAILS_0x */153153+};154154+155155+static const struct regmap_range max77759_charger_volatile_registers[] = {156156+ regmap_reg_range(0xb0, 0xb1), /* INTx */157157+ regmap_reg_range(0xb4, 0xb8),158158+};159159+160160+static const struct regmap_access_table max77759_charger_wr_table = {161161+ .yes_ranges = max77759_charger_registers,162162+ .n_yes_ranges = ARRAY_SIZE(max77759_charger_registers),163163+ .no_ranges = max77759_charger_ro_registers,164164+ .n_no_ranges = ARRAY_SIZE(max77759_charger_ro_registers),165165+};166166+167167+static const struct regmap_access_table max77759_charger_rd_table = {168168+ .yes_ranges = max77759_charger_registers,169169+ .n_yes_ranges = ARRAY_SIZE(max77759_charger_registers),170170+};171171+172172+static const struct regmap_access_table max77759_charger_volatile_table = {173173+ .yes_ranges = max77759_charger_volatile_registers,174174+ .n_yes_ranges = ARRAY_SIZE(max77759_charger_volatile_registers),175175+};176176+177177+static const struct regmap_config max77759_regmap_config_charger = {178178+ .name = "charger",179179+ .reg_bits = 8,180180+ .val_bits = 8,181181+ .max_register = MAX77759_CHGR_REG_CHG_CNFG_19,182182+ .wr_table = &max77759_charger_wr_table,183183+ .rd_table = &max77759_charger_rd_table,184184+ .volatile_table = &max77759_charger_volatile_table,185185+ .num_reg_defaults_raw = MAX77759_CHGR_REG_CHG_CNFG_19 + 1,186186+ .cache_type = REGCACHE_FLAT,187187+};188188+189189+/*190190+ * Interrupts - with the following interrupt hierarchy:191191+ * pmic IRQs (INTSRC)192192+ * - MAXQ_INT: MaxQ IRQs193193+ * - UIC_INT1194194+ * - APCmdResI195195+ * - SysMsgI196196+ * - GPIOxI197197+ * - TOPSYS_INT: topsys198198+ * - TOPSYS_INT199199+ * - TSHDN_INT200200+ * - SYSOVLO_INT201201+ * - SYSUVLO_INT202202+ * - FSHIP_NOT_RD203203+ * - CHGR_INT: charger204204+ * - CHG_INT205205+ * - CHG_INT2206206+ */207207+enum {208208+ MAX77759_INT_MAXQ,209209+ MAX77759_INT_TOPSYS,210210+ MAX77759_INT_CHGR,211211+};212212+213213+enum {214214+ MAX77759_TOPSYS_INT_TSHDN,215215+ MAX77759_TOPSYS_INT_SYSOVLO,216216+ MAX77759_TOPSYS_INT_SYSUVLO,217217+ MAX77759_TOPSYS_INT_FSHIP_NOT_RD,218218+};219219+220220+enum {221221+ MAX77759_MAXQ_INT_APCMDRESI,222222+ MAX77759_MAXQ_INT_SYSMSGI,223223+ MAX77759_MAXQ_INT_GPIO,224224+ MAX77759_MAXQ_INT_UIC1,225225+ MAX77759_MAXQ_INT_UIC2,226226+ MAX77759_MAXQ_INT_UIC3,227227+ MAX77759_MAXQ_INT_UIC4,228228+};229229+230230+enum {231231+ MAX77759_CHARGER_INT_1,232232+ MAX77759_CHARGER_INT_2,233233+};234234+235235+static const struct regmap_irq max77759_pmic_irqs[] = {236236+ REGMAP_IRQ_REG(MAX77759_INT_MAXQ, 0, MAX77759_PMIC_REG_INTSRC_MAXQ),237237+ REGMAP_IRQ_REG(MAX77759_INT_TOPSYS, 0, MAX77759_PMIC_REG_INTSRC_TOPSYS),238238+ REGMAP_IRQ_REG(MAX77759_INT_CHGR, 0, MAX77759_PMIC_REG_INTSRC_CHGR),239239+};240240+241241+static const struct regmap_irq max77759_maxq_irqs[] = {242242+ REGMAP_IRQ_REG(MAX77759_MAXQ_INT_APCMDRESI, 0, MAX77759_MAXQ_REG_UIC_INT1_APCMDRESI),243243+ REGMAP_IRQ_REG(MAX77759_MAXQ_INT_SYSMSGI, 0, MAX77759_MAXQ_REG_UIC_INT1_SYSMSGI),244244+ REGMAP_IRQ_REG(MAX77759_MAXQ_INT_GPIO, 0, GENMASK(1, 0)),245245+ REGMAP_IRQ_REG(MAX77759_MAXQ_INT_UIC1, 0, GENMASK(5, 2)),246246+ REGMAP_IRQ_REG(MAX77759_MAXQ_INT_UIC2, 1, GENMASK(7, 0)),247247+ REGMAP_IRQ_REG(MAX77759_MAXQ_INT_UIC3, 2, GENMASK(7, 0)),248248+ REGMAP_IRQ_REG(MAX77759_MAXQ_INT_UIC4, 3, GENMASK(7, 0)),249249+};250250+251251+static const struct regmap_irq max77759_topsys_irqs[] = {252252+ REGMAP_IRQ_REG(MAX77759_TOPSYS_INT_TSHDN, 0, MAX77759_PMIC_REG_TOPSYS_INT_TSHDN),253253+ REGMAP_IRQ_REG(MAX77759_TOPSYS_INT_SYSOVLO, 0, MAX77759_PMIC_REG_TOPSYS_INT_SYSOVLO),254254+ REGMAP_IRQ_REG(MAX77759_TOPSYS_INT_SYSUVLO, 0, MAX77759_PMIC_REG_TOPSYS_INT_SYSUVLO),255255+ REGMAP_IRQ_REG(MAX77759_TOPSYS_INT_FSHIP_NOT_RD, 0, MAX77759_PMIC_REG_TOPSYS_INT_FSHIP),256256+};257257+258258+static const struct regmap_irq max77759_chgr_irqs[] = {259259+ REGMAP_IRQ_REG(MAX77759_CHARGER_INT_1, 0, GENMASK(7, 0)),260260+ REGMAP_IRQ_REG(MAX77759_CHARGER_INT_2, 1, GENMASK(7, 0)),261261+};262262+263263+static const struct regmap_irq_chip max77759_pmic_irq_chip = {264264+ .name = "max77759-pmic",265265+ /* INTSRC is read-only and doesn't require clearing */266266+ .status_base = MAX77759_PMIC_REG_INTSRC,267267+ .mask_base = MAX77759_PMIC_REG_INTSRCMASK,268268+ .num_regs = 1,269269+ .irqs = max77759_pmic_irqs,270270+ .num_irqs = ARRAY_SIZE(max77759_pmic_irqs),271271+};272272+273273+/*274274+ * We can let regmap-irq auto-ack the topsys interrupt bits as required, but275275+ * for all others the individual drivers need to know which interrupt bit276276+ * exactly is set inside their interrupt handlers, and therefore we can not set277277+ * .ack_base for those.278278+ */279279+static const struct regmap_irq_chip max77759_maxq_irq_chip = {280280+ .name = "max77759-maxq",281281+ .domain_suffix = "MAXQ",282282+ .status_base = MAX77759_MAXQ_REG_UIC_INT1,283283+ .mask_base = MAX77759_MAXQ_REG_UIC_INT1_M,284284+ .num_regs = 4,285285+ .irqs = max77759_maxq_irqs,286286+ .num_irqs = ARRAY_SIZE(max77759_maxq_irqs),287287+};288288+289289+static const struct regmap_irq_chip max77759_topsys_irq_chip = {290290+ .name = "max77759-topsys",291291+ .domain_suffix = "TOPSYS",292292+ .status_base = MAX77759_PMIC_REG_TOPSYS_INT,293293+ .mask_base = MAX77759_PMIC_REG_TOPSYS_INT_MASK,294294+ .ack_base = MAX77759_PMIC_REG_TOPSYS_INT,295295+ .num_regs = 1,296296+ .irqs = max77759_topsys_irqs,297297+ .num_irqs = ARRAY_SIZE(max77759_topsys_irqs),298298+};299299+300300+static const struct regmap_irq_chip max77759_chrg_irq_chip = {301301+ .name = "max77759-chgr",302302+ .domain_suffix = "CHGR",303303+ .status_base = MAX77759_CHGR_REG_CHG_INT,304304+ .mask_base = MAX77759_CHGR_REG_CHG_INT_MASK,305305+ .num_regs = 2,306306+ .irqs = max77759_chgr_irqs,307307+ .num_irqs = ARRAY_SIZE(max77759_chgr_irqs),308308+};309309+310310+static const struct max77759_i2c_subdev max77759_i2c_subdevs[] = {311311+ {312312+ .id = MAX77759_I2C_SUBDEV_ID_MAXQ,313313+ .cfg = &max77759_regmap_config_maxq,314314+ /* I2C address is same as for sub-block 'top' */315315+ },316316+ {317317+ .id = MAX77759_I2C_SUBDEV_ID_CHARGER,318318+ .cfg = &max77759_regmap_config_charger,319319+ .i2c_address = 0x69,320320+ },321321+};322322+323323+static const struct resource max77759_gpio_resources[] = {324324+ DEFINE_RES_IRQ_NAMED(MAX77759_MAXQ_INT_GPIO, "GPI"),325325+};326326+327327+static const struct resource max77759_charger_resources[] = {328328+ DEFINE_RES_IRQ_NAMED(MAX77759_CHARGER_INT_1, "INT1"),329329+ DEFINE_RES_IRQ_NAMED(MAX77759_CHARGER_INT_2, "INT2"),330330+};331331+332332+static const struct mfd_cell max77759_cells[] = {333333+ MFD_CELL_OF("max77759-nvmem", NULL, NULL, 0, 0,334334+ "maxim,max77759-nvmem"),335335+};336336+337337+static const struct mfd_cell max77759_maxq_cells[] = {338338+ MFD_CELL_OF("max77759-gpio", max77759_gpio_resources, NULL, 0, 0,339339+ "maxim,max77759-gpio"),340340+};341341+342342+static const struct mfd_cell max77759_charger_cells[] = {343343+ MFD_CELL_RES("max77759-charger", max77759_charger_resources),344344+};345345+346346+int max77759_maxq_command(struct max77759 *max77759,347347+ const struct max77759_maxq_command *cmd,348348+ struct max77759_maxq_response *rsp)349349+{350350+ DEFINE_FLEX(struct max77759_maxq_response, _rsp, rsp, length, 1);351351+ struct device *dev = regmap_get_device(max77759->regmap_maxq);352352+ static const unsigned int timeout_ms = 200;353353+ int ret;354354+355355+ if (cmd->length > MAX77759_MAXQ_OPCODE_MAXLENGTH)356356+ return -EINVAL;357357+358358+ /*359359+ * As a convenience for API users when issuing simple commands, rsp is360360+ * allowed to be NULL. In that case we need a temporary here to write361361+ * the response to, as we need to verify that the command was indeed362362+ * completed correctly.363363+ */364364+ if (!rsp)365365+ rsp = _rsp;366366+367367+ if (!rsp->length || rsp->length > MAX77759_MAXQ_OPCODE_MAXLENGTH)368368+ return -EINVAL;369369+370370+ guard(mutex)(&max77759->maxq_lock);371371+372372+ reinit_completion(&max77759->cmd_done);373373+374374+ /*375375+ * MaxQ latches the message when the DATAOUT32 register is written. If376376+ * cmd->length is shorter we still need to write 0 to it.377377+ */378378+ ret = regmap_bulk_write(max77759->regmap_maxq,379379+ MAX77759_MAXQ_REG_AP_DATAOUT0, cmd->cmd,380380+ cmd->length);381381+ if (!ret && cmd->length < MAX77759_MAXQ_OPCODE_MAXLENGTH)382382+ ret = regmap_write(max77759->regmap_maxq,383383+ MAX77759_MAXQ_REG_AP_DATAOUT32, 0);384384+ if (ret) {385385+ dev_err(dev, "writing command failed: %d\n", ret);386386+ return ret;387387+ }388388+389389+ /* Wait for response from MaxQ */390390+ if (!wait_for_completion_timeout(&max77759->cmd_done,391391+ msecs_to_jiffies(timeout_ms))) {392392+ dev_err(dev, "timed out waiting for response\n");393393+ return -ETIMEDOUT;394394+ }395395+396396+ ret = regmap_bulk_read(max77759->regmap_maxq,397397+ MAX77759_MAXQ_REG_AP_DATAIN0,398398+ rsp->rsp, rsp->length);399399+ if (ret) {400400+ dev_err(dev, "reading response failed: %d\n", ret);401401+ return ret;402402+ }403403+404404+ /*405405+ * As per the protocol, the first byte of the reply will match the406406+ * request.407407+ */408408+ if (cmd->cmd[0] != rsp->rsp[0]) {409409+ dev_err(dev, "unexpected opcode response for %#.2x: %*ph\n",410410+ cmd->cmd[0], (int)rsp->length, rsp->rsp);411411+ return -EIO;412412+ }413413+414414+ return 0;415415+}416416+EXPORT_SYMBOL_GPL(max77759_maxq_command);417417+418418+static irqreturn_t apcmdres_irq_handler(int irq, void *irq_data)419419+{420420+ struct max77759 *max77759 = irq_data;421421+422422+ regmap_write(max77759->regmap_maxq, MAX77759_MAXQ_REG_UIC_INT1,423423+ MAX77759_MAXQ_REG_UIC_INT1_APCMDRESI);424424+425425+ complete(&max77759->cmd_done);426426+427427+ return IRQ_HANDLED;428428+}429429+430430+static int max77759_create_i2c_subdev(struct i2c_client *client,431431+ struct max77759 *max77759,432432+ const struct max77759_i2c_subdev *sd)433433+{434434+ struct i2c_client *sub;435435+ struct regmap *regmap;436436+ int ret;437437+438438+ /*439439+ * If 'sd' has an I2C address, 'sub' will be assigned a new 'dummy'440440+ * device, otherwise use it as-is.441441+ */442442+ sub = client;443443+ if (sd->i2c_address) {444444+ sub = devm_i2c_new_dummy_device(&client->dev,445445+ client->adapter,446446+ sd->i2c_address);447447+448448+ if (IS_ERR(sub))449449+ return dev_err_probe(&client->dev, PTR_ERR(sub),450450+ "failed to claim I2C device %s\n",451451+ sd->cfg->name);452452+ }453453+454454+ regmap = devm_regmap_init_i2c(sub, sd->cfg);455455+ if (IS_ERR(regmap))456456+ return dev_err_probe(&sub->dev, PTR_ERR(regmap),457457+ "regmap init for '%s' failed\n",458458+ sd->cfg->name);459459+460460+ ret = regmap_attach_dev(&client->dev, regmap, sd->cfg);461461+ if (ret)462462+ return dev_err_probe(&client->dev, ret,463463+ "regmap attach of '%s' failed\n",464464+ sd->cfg->name);465465+466466+ if (sd->id == MAX77759_I2C_SUBDEV_ID_MAXQ)467467+ max77759->regmap_maxq = regmap;468468+ else if (sd->id == MAX77759_I2C_SUBDEV_ID_CHARGER)469469+ max77759->regmap_charger = regmap;470470+471471+ return 0;472472+}473473+474474+static int max77759_add_chained_irq_chip(struct device *dev,475475+ struct regmap *regmap,476476+ int pirq,477477+ struct regmap_irq_chip_data *parent,478478+ const struct regmap_irq_chip *chip,479479+ struct regmap_irq_chip_data **data)480480+{481481+ int irq, ret;482482+483483+ irq = regmap_irq_get_virq(parent, pirq);484484+ if (irq < 0)485485+ return dev_err_probe(dev, irq,486486+ "failed to get parent vIRQ(%d) for chip %s\n",487487+ pirq, chip->name);488488+489489+ ret = devm_regmap_add_irq_chip(dev, regmap, irq,490490+ IRQF_ONESHOT | IRQF_SHARED, 0, chip,491491+ data);492492+ if (ret)493493+ return dev_err_probe(dev, ret, "failed to add %s IRQ chip\n",494494+ chip->name);495495+496496+ return 0;497497+}498498+499499+static int max77759_add_chained_maxq(struct i2c_client *client,500500+ struct max77759 *max77759,501501+ struct regmap_irq_chip_data *parent)502502+{503503+ struct regmap_irq_chip_data *irq_chip_data;504504+ int apcmdres_irq;505505+ int ret;506506+507507+ ret = max77759_add_chained_irq_chip(&client->dev,508508+ max77759->regmap_maxq,509509+ MAX77759_INT_MAXQ,510510+ parent,511511+ &max77759_maxq_irq_chip,512512+ &irq_chip_data);513513+ if (ret)514514+ return ret;515515+516516+ init_completion(&max77759->cmd_done);517517+ apcmdres_irq = regmap_irq_get_virq(irq_chip_data,518518+ MAX77759_MAXQ_INT_APCMDRESI);519519+520520+ ret = devm_request_threaded_irq(&client->dev, apcmdres_irq,521521+ NULL, apcmdres_irq_handler,522522+ IRQF_ONESHOT | IRQF_SHARED,523523+ dev_name(&client->dev), max77759);524524+ if (ret)525525+ return dev_err_probe(&client->dev, ret,526526+ "MAX77759_MAXQ_INT_APCMDRESI failed\n");527527+528528+ ret = devm_mfd_add_devices(&client->dev, PLATFORM_DEVID_AUTO,529529+ max77759_maxq_cells,530530+ ARRAY_SIZE(max77759_maxq_cells),531531+ NULL, 0,532532+ regmap_irq_get_domain(irq_chip_data));533533+ if (ret)534534+ return dev_err_probe(&client->dev, ret,535535+ "failed to add child devices (MaxQ)\n");536536+537537+ return 0;538538+}539539+540540+static int max77759_add_chained_topsys(struct i2c_client *client,541541+ struct max77759 *max77759,542542+ struct regmap_irq_chip_data *parent)543543+{544544+ struct regmap_irq_chip_data *irq_chip_data;545545+ int ret;546546+547547+ ret = max77759_add_chained_irq_chip(&client->dev,548548+ max77759->regmap_top,549549+ MAX77759_INT_TOPSYS,550550+ parent,551551+ &max77759_topsys_irq_chip,552552+ &irq_chip_data);553553+ if (ret)554554+ return ret;555555+556556+ return 0;557557+}558558+559559+static int max77759_add_chained_charger(struct i2c_client *client,560560+ struct max77759 *max77759,561561+ struct regmap_irq_chip_data *parent)562562+{563563+ struct regmap_irq_chip_data *irq_chip_data;564564+ int ret;565565+566566+ ret = max77759_add_chained_irq_chip(&client->dev,567567+ max77759->regmap_charger,568568+ MAX77759_INT_CHGR,569569+ parent,570570+ &max77759_chrg_irq_chip,571571+ &irq_chip_data);572572+ if (ret)573573+ return ret;574574+575575+ ret = devm_mfd_add_devices(&client->dev, PLATFORM_DEVID_AUTO,576576+ max77759_charger_cells,577577+ ARRAY_SIZE(max77759_charger_cells),578578+ NULL, 0,579579+ regmap_irq_get_domain(irq_chip_data));580580+ if (ret)581581+ return dev_err_probe(&client->dev, ret,582582+ "failed to add child devices (charger)\n");583583+584584+ return 0;585585+}586586+587587+static int max77759_probe(struct i2c_client *client)588588+{589589+ struct regmap_irq_chip_data *irq_chip_data_pmic;590590+ struct irq_data *irq_data;591591+ struct max77759 *max77759;592592+ unsigned long irq_flags;593593+ unsigned int pmic_id;594594+ int ret;595595+596596+ max77759 = devm_kzalloc(&client->dev, sizeof(*max77759), GFP_KERNEL);597597+ if (!max77759)598598+ return -ENOMEM;599599+600600+ i2c_set_clientdata(client, max77759);601601+602602+ max77759->regmap_top = devm_regmap_init_i2c(client,603603+ &max77759_regmap_config_top);604604+ if (IS_ERR(max77759->regmap_top))605605+ return dev_err_probe(&client->dev, PTR_ERR(max77759->regmap_top),606606+ "regmap init for '%s' failed\n",607607+ max77759_regmap_config_top.name);608608+609609+ ret = regmap_read(max77759->regmap_top,610610+ MAX77759_PMIC_REG_PMIC_ID, &pmic_id);611611+ if (ret)612612+ return dev_err_probe(&client->dev, ret,613613+ "unable to read device ID\n");614614+615615+ if (pmic_id != MAX77759_CHIP_ID)616616+ return dev_err_probe(&client->dev, -ENODEV,617617+ "unsupported device ID %#.2x (%d)\n",618618+ pmic_id, pmic_id);619619+620620+ ret = devm_mutex_init(&client->dev, &max77759->maxq_lock);621621+ if (ret)622622+ return ret;623623+624624+ for (int i = 0; i < ARRAY_SIZE(max77759_i2c_subdevs); i++) {625625+ ret = max77759_create_i2c_subdev(client, max77759,626626+ &max77759_i2c_subdevs[i]);627627+ if (ret)628628+ return ret;629629+ }630630+631631+ irq_data = irq_get_irq_data(client->irq);632632+ if (!irq_data)633633+ return dev_err_probe(&client->dev, -EINVAL,634634+ "invalid IRQ: %d\n", client->irq);635635+636636+ irq_flags = IRQF_ONESHOT | IRQF_SHARED;637637+ irq_flags |= irqd_get_trigger_type(irq_data);638638+639639+ ret = devm_regmap_add_irq_chip(&client->dev, max77759->regmap_top,640640+ client->irq, irq_flags, 0,641641+ &max77759_pmic_irq_chip,642642+ &irq_chip_data_pmic);643643+ if (ret)644644+ return dev_err_probe(&client->dev, ret,645645+ "failed to add IRQ chip '%s'\n",646646+ max77759_pmic_irq_chip.name);647647+648648+ ret = max77759_add_chained_maxq(client, max77759, irq_chip_data_pmic);649649+ if (ret)650650+ return ret;651651+652652+ ret = max77759_add_chained_topsys(client, max77759, irq_chip_data_pmic);653653+ if (ret)654654+ return ret;655655+656656+ ret = max77759_add_chained_charger(client, max77759, irq_chip_data_pmic);657657+ if (ret)658658+ return ret;659659+660660+ return devm_mfd_add_devices(&client->dev, PLATFORM_DEVID_AUTO,661661+ max77759_cells, ARRAY_SIZE(max77759_cells),662662+ NULL, 0,663663+ regmap_irq_get_domain(irq_chip_data_pmic));664664+}665665+666666+static const struct i2c_device_id max77759_i2c_id[] = {667667+ { "max77759" },668668+ { }669669+};670670+MODULE_DEVICE_TABLE(i2c, max77759_i2c_id);671671+672672+static const struct of_device_id max77759_of_id[] = {673673+ { .compatible = "maxim,max77759", },674674+ { }675675+};676676+MODULE_DEVICE_TABLE(of, max77759_of_id);677677+678678+static struct i2c_driver max77759_i2c_driver = {679679+ .driver = {680680+ .name = "max77759",681681+ .of_match_table = max77759_of_id,682682+ },683683+ .probe = max77759_probe,684684+ .id_table = max77759_i2c_id,685685+};686686+module_i2c_driver(max77759_i2c_driver);687687+688688+MODULE_AUTHOR("André Draszik <andre.draszik@linaro.org>");689689+MODULE_DESCRIPTION("Maxim MAX77759 core driver");690690+MODULE_LICENSE("GPL");
+423-110
drivers/mfd/rohm-bd96801.c
···3838#include <linux/types.h>39394040#include <linux/mfd/rohm-bd96801.h>4141+#include <linux/mfd/rohm-bd96802.h>4142#include <linux/mfd/rohm-generic.h>42434343-static const struct resource regulator_errb_irqs[] = {4444- DEFINE_RES_IRQ_NAMED(BD96801_OTP_ERR_STAT, "bd96801-otp-err"),4545- DEFINE_RES_IRQ_NAMED(BD96801_DBIST_ERR_STAT, "bd96801-dbist-err"),4646- DEFINE_RES_IRQ_NAMED(BD96801_EEP_ERR_STAT, "bd96801-eep-err"),4747- DEFINE_RES_IRQ_NAMED(BD96801_ABIST_ERR_STAT, "bd96801-abist-err"),4848- DEFINE_RES_IRQ_NAMED(BD96801_PRSTB_ERR_STAT, "bd96801-prstb-err"),4949- DEFINE_RES_IRQ_NAMED(BD96801_DRMOS1_ERR_STAT, "bd96801-drmoserr1"),5050- DEFINE_RES_IRQ_NAMED(BD96801_DRMOS2_ERR_STAT, "bd96801-drmoserr2"),5151- DEFINE_RES_IRQ_NAMED(BD96801_SLAVE_ERR_STAT, "bd96801-slave-err"),5252- DEFINE_RES_IRQ_NAMED(BD96801_VREF_ERR_STAT, "bd96801-vref-err"),5353- DEFINE_RES_IRQ_NAMED(BD96801_TSD_ERR_STAT, "bd96801-tsd"),5454- DEFINE_RES_IRQ_NAMED(BD96801_UVLO_ERR_STAT, "bd96801-uvlo-err"),5555- DEFINE_RES_IRQ_NAMED(BD96801_OVLO_ERR_STAT, "bd96801-ovlo-err"),5656- DEFINE_RES_IRQ_NAMED(BD96801_OSC_ERR_STAT, "bd96801-osc-err"),5757- DEFINE_RES_IRQ_NAMED(BD96801_PON_ERR_STAT, "bd96801-pon-err"),5858- DEFINE_RES_IRQ_NAMED(BD96801_POFF_ERR_STAT, "bd96801-poff-err"),5959- DEFINE_RES_IRQ_NAMED(BD96801_CMD_SHDN_ERR_STAT, "bd96801-cmd-shdn-err"),4444+struct bd968xx {4545+ const struct resource *errb_irqs;4646+ const struct resource *intb_irqs;4747+ int num_errb_irqs;4848+ int num_intb_irqs;4949+ const struct regmap_irq_chip *errb_irq_chip;5050+ const struct regmap_irq_chip *intb_irq_chip;5151+ const struct regmap_config *regmap_config;5252+ struct mfd_cell *cells;5353+ int num_cells;5454+ int unlock_reg;5555+ int unlock_val;5656+};5757+5858+static const struct resource bd96801_reg_errb_irqs[] = {5959+ DEFINE_RES_IRQ_NAMED(BD96801_OTP_ERR_STAT, "otp-err"),6060+ DEFINE_RES_IRQ_NAMED(BD96801_DBIST_ERR_STAT, "dbist-err"),6161+ DEFINE_RES_IRQ_NAMED(BD96801_EEP_ERR_STAT, "eep-err"),6262+ DEFINE_RES_IRQ_NAMED(BD96801_ABIST_ERR_STAT, "abist-err"),6363+ DEFINE_RES_IRQ_NAMED(BD96801_PRSTB_ERR_STAT, "prstb-err"),6464+ DEFINE_RES_IRQ_NAMED(BD96801_DRMOS1_ERR_STAT, "drmoserr1"),6565+ DEFINE_RES_IRQ_NAMED(BD96801_DRMOS2_ERR_STAT, "drmoserr2"),6666+ DEFINE_RES_IRQ_NAMED(BD96801_SLAVE_ERR_STAT, "slave-err"),6767+ DEFINE_RES_IRQ_NAMED(BD96801_VREF_ERR_STAT, "vref-err"),6868+ DEFINE_RES_IRQ_NAMED(BD96801_TSD_ERR_STAT, "tsd"),6969+ DEFINE_RES_IRQ_NAMED(BD96801_UVLO_ERR_STAT, "uvlo-err"),7070+ DEFINE_RES_IRQ_NAMED(BD96801_OVLO_ERR_STAT, "ovlo-err"),7171+ DEFINE_RES_IRQ_NAMED(BD96801_OSC_ERR_STAT, "osc-err"),7272+ DEFINE_RES_IRQ_NAMED(BD96801_PON_ERR_STAT, "pon-err"),7373+ DEFINE_RES_IRQ_NAMED(BD96801_POFF_ERR_STAT, "poff-err"),7474+ DEFINE_RES_IRQ_NAMED(BD96801_CMD_SHDN_ERR_STAT, "cmd-shdn-err"),60756176 DEFINE_RES_IRQ_NAMED(BD96801_INT_PRSTB_WDT_ERR, "bd96801-prstb-wdt-err"),6277 DEFINE_RES_IRQ_NAMED(BD96801_INT_CHIP_IF_ERR, "bd96801-chip-if-err"),6363- DEFINE_RES_IRQ_NAMED(BD96801_INT_SHDN_ERR_STAT, "bd96801-int-shdn-err"),64786565- DEFINE_RES_IRQ_NAMED(BD96801_BUCK1_PVIN_ERR_STAT, "bd96801-buck1-pvin-err"),6666- DEFINE_RES_IRQ_NAMED(BD96801_BUCK1_OVP_ERR_STAT, "bd96801-buck1-ovp-err"),6767- DEFINE_RES_IRQ_NAMED(BD96801_BUCK1_UVP_ERR_STAT, "bd96801-buck1-uvp-err"),6868- DEFINE_RES_IRQ_NAMED(BD96801_BUCK1_SHDN_ERR_STAT, "bd96801-buck1-shdn-err"),7979+ DEFINE_RES_IRQ_NAMED(BD96801_INT_SHDN_ERR_STAT, "int-shdn-err"),69807070- DEFINE_RES_IRQ_NAMED(BD96801_BUCK2_PVIN_ERR_STAT, "bd96801-buck2-pvin-err"),7171- DEFINE_RES_IRQ_NAMED(BD96801_BUCK2_OVP_ERR_STAT, "bd96801-buck2-ovp-err"),7272- DEFINE_RES_IRQ_NAMED(BD96801_BUCK2_UVP_ERR_STAT, "bd96801-buck2-uvp-err"),7373- DEFINE_RES_IRQ_NAMED(BD96801_BUCK2_SHDN_ERR_STAT, "bd96801-buck2-shdn-err"),8181+ DEFINE_RES_IRQ_NAMED(BD96801_BUCK1_PVIN_ERR_STAT, "buck1-pvin-err"),8282+ DEFINE_RES_IRQ_NAMED(BD96801_BUCK1_OVP_ERR_STAT, "buck1-ovp-err"),8383+ DEFINE_RES_IRQ_NAMED(BD96801_BUCK1_UVP_ERR_STAT, "buck1-uvp-err"),8484+ DEFINE_RES_IRQ_NAMED(BD96801_BUCK1_SHDN_ERR_STAT, "buck1-shdn-err"),74857575- DEFINE_RES_IRQ_NAMED(BD96801_BUCK3_PVIN_ERR_STAT, "bd96801-buck3-pvin-err"),7676- DEFINE_RES_IRQ_NAMED(BD96801_BUCK3_OVP_ERR_STAT, "bd96801-buck3-ovp-err"),7777- DEFINE_RES_IRQ_NAMED(BD96801_BUCK3_UVP_ERR_STAT, "bd96801-buck3-uvp-err"),7878- DEFINE_RES_IRQ_NAMED(BD96801_BUCK3_SHDN_ERR_STAT, "bd96801-buck3-shdn-err"),8686+ DEFINE_RES_IRQ_NAMED(BD96801_BUCK2_PVIN_ERR_STAT, "buck2-pvin-err"),8787+ DEFINE_RES_IRQ_NAMED(BD96801_BUCK2_OVP_ERR_STAT, "buck2-ovp-err"),8888+ DEFINE_RES_IRQ_NAMED(BD96801_BUCK2_UVP_ERR_STAT, "buck2-uvp-err"),8989+ DEFINE_RES_IRQ_NAMED(BD96801_BUCK2_SHDN_ERR_STAT, "buck2-shdn-err"),79908080- DEFINE_RES_IRQ_NAMED(BD96801_BUCK4_PVIN_ERR_STAT, "bd96801-buck4-pvin-err"),8181- DEFINE_RES_IRQ_NAMED(BD96801_BUCK4_OVP_ERR_STAT, "bd96801-buck4-ovp-err"),8282- DEFINE_RES_IRQ_NAMED(BD96801_BUCK4_UVP_ERR_STAT, "bd96801-buck4-uvp-err"),8383- DEFINE_RES_IRQ_NAMED(BD96801_BUCK4_SHDN_ERR_STAT, "bd96801-buck4-shdn-err"),9191+ DEFINE_RES_IRQ_NAMED(BD96801_BUCK3_PVIN_ERR_STAT, "buck3-pvin-err"),9292+ DEFINE_RES_IRQ_NAMED(BD96801_BUCK3_OVP_ERR_STAT, "buck3-ovp-err"),9393+ DEFINE_RES_IRQ_NAMED(BD96801_BUCK3_UVP_ERR_STAT, "buck3-uvp-err"),9494+ DEFINE_RES_IRQ_NAMED(BD96801_BUCK3_SHDN_ERR_STAT, "buck3-shdn-err"),84958585- DEFINE_RES_IRQ_NAMED(BD96801_LDO5_PVIN_ERR_STAT, "bd96801-ldo5-pvin-err"),8686- DEFINE_RES_IRQ_NAMED(BD96801_LDO5_OVP_ERR_STAT, "bd96801-ldo5-ovp-err"),8787- DEFINE_RES_IRQ_NAMED(BD96801_LDO5_UVP_ERR_STAT, "bd96801-ldo5-uvp-err"),8888- DEFINE_RES_IRQ_NAMED(BD96801_LDO5_SHDN_ERR_STAT, "bd96801-ldo5-shdn-err"),9696+ DEFINE_RES_IRQ_NAMED(BD96801_BUCK4_PVIN_ERR_STAT, "buck4-pvin-err"),9797+ DEFINE_RES_IRQ_NAMED(BD96801_BUCK4_OVP_ERR_STAT, "buck4-ovp-err"),9898+ DEFINE_RES_IRQ_NAMED(BD96801_BUCK4_UVP_ERR_STAT, "buck4-uvp-err"),9999+ DEFINE_RES_IRQ_NAMED(BD96801_BUCK4_SHDN_ERR_STAT, "buck4-shdn-err"),891009090- DEFINE_RES_IRQ_NAMED(BD96801_LDO6_PVIN_ERR_STAT, "bd96801-ldo6-pvin-err"),9191- DEFINE_RES_IRQ_NAMED(BD96801_LDO6_OVP_ERR_STAT, "bd96801-ldo6-ovp-err"),9292- DEFINE_RES_IRQ_NAMED(BD96801_LDO6_UVP_ERR_STAT, "bd96801-ldo6-uvp-err"),9393- DEFINE_RES_IRQ_NAMED(BD96801_LDO6_SHDN_ERR_STAT, "bd96801-ldo6-shdn-err"),101101+ DEFINE_RES_IRQ_NAMED(BD96801_LDO5_PVIN_ERR_STAT, "ldo5-pvin-err"),102102+ DEFINE_RES_IRQ_NAMED(BD96801_LDO5_OVP_ERR_STAT, "ldo5-ovp-err"),103103+ DEFINE_RES_IRQ_NAMED(BD96801_LDO5_UVP_ERR_STAT, "ldo5-uvp-err"),104104+ DEFINE_RES_IRQ_NAMED(BD96801_LDO5_SHDN_ERR_STAT, "ldo5-shdn-err"),941059595- DEFINE_RES_IRQ_NAMED(BD96801_LDO7_PVIN_ERR_STAT, "bd96801-ldo7-pvin-err"),9696- DEFINE_RES_IRQ_NAMED(BD96801_LDO7_OVP_ERR_STAT, "bd96801-ldo7-ovp-err"),9797- DEFINE_RES_IRQ_NAMED(BD96801_LDO7_UVP_ERR_STAT, "bd96801-ldo7-uvp-err"),9898- DEFINE_RES_IRQ_NAMED(BD96801_LDO7_SHDN_ERR_STAT, "bd96801-ldo7-shdn-err"),106106+ DEFINE_RES_IRQ_NAMED(BD96801_LDO6_PVIN_ERR_STAT, "ldo6-pvin-err"),107107+ DEFINE_RES_IRQ_NAMED(BD96801_LDO6_OVP_ERR_STAT, "ldo6-ovp-err"),108108+ DEFINE_RES_IRQ_NAMED(BD96801_LDO6_UVP_ERR_STAT, "ldo6-uvp-err"),109109+ DEFINE_RES_IRQ_NAMED(BD96801_LDO6_SHDN_ERR_STAT, "ldo6-shdn-err"),110110+111111+ DEFINE_RES_IRQ_NAMED(BD96801_LDO7_PVIN_ERR_STAT, "ldo7-pvin-err"),112112+ DEFINE_RES_IRQ_NAMED(BD96801_LDO7_OVP_ERR_STAT, "ldo7-ovp-err"),113113+ DEFINE_RES_IRQ_NAMED(BD96801_LDO7_UVP_ERR_STAT, "ldo7-uvp-err"),114114+ DEFINE_RES_IRQ_NAMED(BD96801_LDO7_SHDN_ERR_STAT, "ldo7-shdn-err"),99115};100116101101-static const struct resource regulator_intb_irqs[] = {102102- DEFINE_RES_IRQ_NAMED(BD96801_TW_STAT, "bd96801-core-thermal"),117117+static const struct resource bd96802_reg_errb_irqs[] = {118118+ DEFINE_RES_IRQ_NAMED(BD96802_OTP_ERR_STAT, "otp-err"),119119+ DEFINE_RES_IRQ_NAMED(BD96802_DBIST_ERR_STAT, "dbist-err"),120120+ DEFINE_RES_IRQ_NAMED(BD96802_EEP_ERR_STAT, "eep-err"),121121+ DEFINE_RES_IRQ_NAMED(BD96802_ABIST_ERR_STAT, "abist-err"),122122+ DEFINE_RES_IRQ_NAMED(BD96802_PRSTB_ERR_STAT, "prstb-err"),123123+ DEFINE_RES_IRQ_NAMED(BD96802_DRMOS1_ERR_STAT, "drmoserr1"),124124+ DEFINE_RES_IRQ_NAMED(BD96802_DRMOS1_ERR_STAT, "drmoserr2"),125125+ DEFINE_RES_IRQ_NAMED(BD96802_SLAVE_ERR_STAT, "slave-err"),126126+ DEFINE_RES_IRQ_NAMED(BD96802_VREF_ERR_STAT, "vref-err"),127127+ DEFINE_RES_IRQ_NAMED(BD96802_TSD_ERR_STAT, "tsd"),128128+ DEFINE_RES_IRQ_NAMED(BD96802_UVLO_ERR_STAT, "uvlo-err"),129129+ DEFINE_RES_IRQ_NAMED(BD96802_OVLO_ERR_STAT, "ovlo-err"),130130+ DEFINE_RES_IRQ_NAMED(BD96802_OSC_ERR_STAT, "osc-err"),131131+ DEFINE_RES_IRQ_NAMED(BD96802_PON_ERR_STAT, "pon-err"),132132+ DEFINE_RES_IRQ_NAMED(BD96802_POFF_ERR_STAT, "poff-err"),133133+ DEFINE_RES_IRQ_NAMED(BD96802_CMD_SHDN_ERR_STAT, "cmd-shdn-err"),134134+ DEFINE_RES_IRQ_NAMED(BD96802_INT_SHDN_ERR_STAT, "int-shdn-err"),103135104104- DEFINE_RES_IRQ_NAMED(BD96801_BUCK1_OCPH_STAT, "bd96801-buck1-overcurr-h"),105105- DEFINE_RES_IRQ_NAMED(BD96801_BUCK1_OCPL_STAT, "bd96801-buck1-overcurr-l"),106106- DEFINE_RES_IRQ_NAMED(BD96801_BUCK1_OCPN_STAT, "bd96801-buck1-overcurr-n"),107107- DEFINE_RES_IRQ_NAMED(BD96801_BUCK1_OVD_STAT, "bd96801-buck1-overvolt"),108108- DEFINE_RES_IRQ_NAMED(BD96801_BUCK1_UVD_STAT, "bd96801-buck1-undervolt"),109109- DEFINE_RES_IRQ_NAMED(BD96801_BUCK1_TW_CH_STAT, "bd96801-buck1-thermal"),136136+ DEFINE_RES_IRQ_NAMED(BD96802_BUCK1_PVIN_ERR_STAT, "buck1-pvin-err"),137137+ DEFINE_RES_IRQ_NAMED(BD96802_BUCK1_OVP_ERR_STAT, "buck1-ovp-err"),138138+ DEFINE_RES_IRQ_NAMED(BD96802_BUCK1_UVP_ERR_STAT, "buck1-uvp-err"),139139+ DEFINE_RES_IRQ_NAMED(BD96802_BUCK1_SHDN_ERR_STAT, "buck1-shdn-err"),110140111111- DEFINE_RES_IRQ_NAMED(BD96801_BUCK2_OCPH_STAT, "bd96801-buck2-overcurr-h"),112112- DEFINE_RES_IRQ_NAMED(BD96801_BUCK2_OCPL_STAT, "bd96801-buck2-overcurr-l"),113113- DEFINE_RES_IRQ_NAMED(BD96801_BUCK2_OCPN_STAT, "bd96801-buck2-overcurr-n"),114114- DEFINE_RES_IRQ_NAMED(BD96801_BUCK2_OVD_STAT, "bd96801-buck2-overvolt"),115115- DEFINE_RES_IRQ_NAMED(BD96801_BUCK2_UVD_STAT, "bd96801-buck2-undervolt"),116116- DEFINE_RES_IRQ_NAMED(BD96801_BUCK2_TW_CH_STAT, "bd96801-buck2-thermal"),141141+ DEFINE_RES_IRQ_NAMED(BD96802_BUCK2_PVIN_ERR_STAT, "buck2-pvin-err"),142142+ DEFINE_RES_IRQ_NAMED(BD96802_BUCK2_OVP_ERR_STAT, "buck2-ovp-err"),143143+ DEFINE_RES_IRQ_NAMED(BD96802_BUCK2_UVP_ERR_STAT, "buck2-uvp-err"),144144+ DEFINE_RES_IRQ_NAMED(BD96802_BUCK2_SHDN_ERR_STAT, "buck2-shdn-err"),145145+};117146118118- DEFINE_RES_IRQ_NAMED(BD96801_BUCK3_OCPH_STAT, "bd96801-buck3-overcurr-h"),119119- DEFINE_RES_IRQ_NAMED(BD96801_BUCK3_OCPL_STAT, "bd96801-buck3-overcurr-l"),120120- DEFINE_RES_IRQ_NAMED(BD96801_BUCK3_OCPN_STAT, "bd96801-buck3-overcurr-n"),121121- DEFINE_RES_IRQ_NAMED(BD96801_BUCK3_OVD_STAT, "bd96801-buck3-overvolt"),122122- DEFINE_RES_IRQ_NAMED(BD96801_BUCK3_UVD_STAT, "bd96801-buck3-undervolt"),123123- DEFINE_RES_IRQ_NAMED(BD96801_BUCK3_TW_CH_STAT, "bd96801-buck3-thermal"),147147+static const struct resource bd96801_reg_intb_irqs[] = {148148+ DEFINE_RES_IRQ_NAMED(BD96801_TW_STAT, "core-thermal"),124149125125- DEFINE_RES_IRQ_NAMED(BD96801_BUCK4_OCPH_STAT, "bd96801-buck4-overcurr-h"),126126- DEFINE_RES_IRQ_NAMED(BD96801_BUCK4_OCPL_STAT, "bd96801-buck4-overcurr-l"),127127- DEFINE_RES_IRQ_NAMED(BD96801_BUCK4_OCPN_STAT, "bd96801-buck4-overcurr-n"),128128- DEFINE_RES_IRQ_NAMED(BD96801_BUCK4_OVD_STAT, "bd96801-buck4-overvolt"),129129- DEFINE_RES_IRQ_NAMED(BD96801_BUCK4_UVD_STAT, "bd96801-buck4-undervolt"),130130- DEFINE_RES_IRQ_NAMED(BD96801_BUCK4_TW_CH_STAT, "bd96801-buck4-thermal"),150150+ DEFINE_RES_IRQ_NAMED(BD96801_BUCK1_OCPH_STAT, "buck1-overcurr-h"),151151+ DEFINE_RES_IRQ_NAMED(BD96801_BUCK1_OCPL_STAT, "buck1-overcurr-l"),152152+ DEFINE_RES_IRQ_NAMED(BD96801_BUCK1_OCPN_STAT, "buck1-overcurr-n"),153153+ DEFINE_RES_IRQ_NAMED(BD96801_BUCK1_OVD_STAT, "buck1-overvolt"),154154+ DEFINE_RES_IRQ_NAMED(BD96801_BUCK1_UVD_STAT, "buck1-undervolt"),155155+ DEFINE_RES_IRQ_NAMED(BD96801_BUCK1_TW_CH_STAT, "buck1-thermal"),131156132132- DEFINE_RES_IRQ_NAMED(BD96801_LDO5_OCPH_STAT, "bd96801-ldo5-overcurr"),133133- DEFINE_RES_IRQ_NAMED(BD96801_LDO5_OVD_STAT, "bd96801-ldo5-overvolt"),134134- DEFINE_RES_IRQ_NAMED(BD96801_LDO5_UVD_STAT, "bd96801-ldo5-undervolt"),157157+ DEFINE_RES_IRQ_NAMED(BD96801_BUCK2_OCPH_STAT, "buck2-overcurr-h"),158158+ DEFINE_RES_IRQ_NAMED(BD96801_BUCK2_OCPL_STAT, "buck2-overcurr-l"),159159+ DEFINE_RES_IRQ_NAMED(BD96801_BUCK2_OCPN_STAT, "buck2-overcurr-n"),160160+ DEFINE_RES_IRQ_NAMED(BD96801_BUCK2_OVD_STAT, "buck2-overvolt"),161161+ DEFINE_RES_IRQ_NAMED(BD96801_BUCK2_UVD_STAT, "buck2-undervolt"),162162+ DEFINE_RES_IRQ_NAMED(BD96801_BUCK2_TW_CH_STAT, "buck2-thermal"),135163136136- DEFINE_RES_IRQ_NAMED(BD96801_LDO6_OCPH_STAT, "bd96801-ldo6-overcurr"),137137- DEFINE_RES_IRQ_NAMED(BD96801_LDO6_OVD_STAT, "bd96801-ldo6-overvolt"),138138- DEFINE_RES_IRQ_NAMED(BD96801_LDO6_UVD_STAT, "bd96801-ldo6-undervolt"),164164+ DEFINE_RES_IRQ_NAMED(BD96801_BUCK3_OCPH_STAT, "buck3-overcurr-h"),165165+ DEFINE_RES_IRQ_NAMED(BD96801_BUCK3_OCPL_STAT, "buck3-overcurr-l"),166166+ DEFINE_RES_IRQ_NAMED(BD96801_BUCK3_OCPN_STAT, "buck3-overcurr-n"),167167+ DEFINE_RES_IRQ_NAMED(BD96801_BUCK3_OVD_STAT, "buck3-overvolt"),168168+ DEFINE_RES_IRQ_NAMED(BD96801_BUCK3_UVD_STAT, "buck3-undervolt"),169169+ DEFINE_RES_IRQ_NAMED(BD96801_BUCK3_TW_CH_STAT, "buck3-thermal"),139170140140- DEFINE_RES_IRQ_NAMED(BD96801_LDO7_OCPH_STAT, "bd96801-ldo7-overcurr"),141141- DEFINE_RES_IRQ_NAMED(BD96801_LDO7_OVD_STAT, "bd96801-ldo7-overvolt"),142142- DEFINE_RES_IRQ_NAMED(BD96801_LDO7_UVD_STAT, "bd96801-ldo7-undervolt"),171171+ DEFINE_RES_IRQ_NAMED(BD96801_BUCK4_OCPH_STAT, "buck4-overcurr-h"),172172+ DEFINE_RES_IRQ_NAMED(BD96801_BUCK4_OCPL_STAT, "buck4-overcurr-l"),173173+ DEFINE_RES_IRQ_NAMED(BD96801_BUCK4_OCPN_STAT, "buck4-overcurr-n"),174174+ DEFINE_RES_IRQ_NAMED(BD96801_BUCK4_OVD_STAT, "buck4-overvolt"),175175+ DEFINE_RES_IRQ_NAMED(BD96801_BUCK4_UVD_STAT, "buck4-undervolt"),176176+ DEFINE_RES_IRQ_NAMED(BD96801_BUCK4_TW_CH_STAT, "buck4-thermal"),177177+178178+ DEFINE_RES_IRQ_NAMED(BD96801_LDO5_OCPH_STAT, "ldo5-overcurr"),179179+ DEFINE_RES_IRQ_NAMED(BD96801_LDO5_OVD_STAT, "ldo5-overvolt"),180180+ DEFINE_RES_IRQ_NAMED(BD96801_LDO5_UVD_STAT, "ldo5-undervolt"),181181+182182+ DEFINE_RES_IRQ_NAMED(BD96801_LDO6_OCPH_STAT, "ldo6-overcurr"),183183+ DEFINE_RES_IRQ_NAMED(BD96801_LDO6_OVD_STAT, "ldo6-overvolt"),184184+ DEFINE_RES_IRQ_NAMED(BD96801_LDO6_UVD_STAT, "ldo6-undervolt"),185185+186186+ DEFINE_RES_IRQ_NAMED(BD96801_LDO7_OCPH_STAT, "ldo7-overcurr"),187187+ DEFINE_RES_IRQ_NAMED(BD96801_LDO7_OVD_STAT, "ldo7-overvolt"),188188+ DEFINE_RES_IRQ_NAMED(BD96801_LDO7_UVD_STAT, "ldo7-undervolt"),189189+};190190+191191+static const struct resource bd96802_reg_intb_irqs[] = {192192+ DEFINE_RES_IRQ_NAMED(BD96802_TW_STAT, "core-thermal"),193193+194194+ DEFINE_RES_IRQ_NAMED(BD96802_BUCK1_OCPH_STAT, "buck1-overcurr-h"),195195+ DEFINE_RES_IRQ_NAMED(BD96802_BUCK1_OCPL_STAT, "buck1-overcurr-l"),196196+ DEFINE_RES_IRQ_NAMED(BD96802_BUCK1_OCPN_STAT, "buck1-overcurr-n"),197197+ DEFINE_RES_IRQ_NAMED(BD96802_BUCK1_OVD_STAT, "buck1-overvolt"),198198+ DEFINE_RES_IRQ_NAMED(BD96802_BUCK1_UVD_STAT, "buck1-undervolt"),199199+ DEFINE_RES_IRQ_NAMED(BD96802_BUCK1_TW_CH_STAT, "buck1-thermal"),200200+201201+ DEFINE_RES_IRQ_NAMED(BD96802_BUCK2_OCPH_STAT, "buck2-overcurr-h"),202202+ DEFINE_RES_IRQ_NAMED(BD96802_BUCK2_OCPL_STAT, "buck2-overcurr-l"),203203+ DEFINE_RES_IRQ_NAMED(BD96802_BUCK2_OCPN_STAT, "buck2-overcurr-n"),204204+ DEFINE_RES_IRQ_NAMED(BD96802_BUCK2_OVD_STAT, "buck2-overvolt"),205205+ DEFINE_RES_IRQ_NAMED(BD96802_BUCK2_UVD_STAT, "buck2-undervolt"),206206+ DEFINE_RES_IRQ_NAMED(BD96802_BUCK2_TW_CH_STAT, "buck2-thermal"),143207};144208145209enum {···214150static struct mfd_cell bd96801_cells[] = {215151 [WDG_CELL] = { .name = "bd96801-wdt", },216152 [REGULATOR_CELL] = { .name = "bd96801-regulator", },153153+};154154+155155+static struct mfd_cell bd96802_cells[] = {156156+ [WDG_CELL] = { .name = "bd96801-wdt", },157157+ [REGULATOR_CELL] = { .name = "bd96802-regulator", },158158+};159159+static struct mfd_cell bd96805_cells[] = {160160+ [WDG_CELL] = { .name = "bd96801-wdt", },161161+ [REGULATOR_CELL] = { .name = "bd96805-regulator", },162162+};163163+164164+static struct mfd_cell bd96806_cells[] = {165165+ [WDG_CELL] = { .name = "bd96806-wdt", },166166+ [REGULATOR_CELL] = { .name = "bd96806-regulator", },217167};218168219169static const struct regmap_range bd96801_volatile_ranges[] = {···247169 regmap_reg_range(BD96801_LDO5_VOL_LVL_REG, BD96801_LDO7_VOL_LVL_REG),248170};249171250250-static const struct regmap_access_table volatile_regs = {172172+static const struct regmap_range bd96802_volatile_ranges[] = {173173+ /* Status regs */174174+ regmap_reg_range(BD96801_REG_WD_FEED, BD96801_REG_WD_FAILCOUNT),175175+ regmap_reg_range(BD96801_REG_WD_ASK, BD96801_REG_WD_ASK),176176+ regmap_reg_range(BD96801_REG_WD_STATUS, BD96801_REG_WD_STATUS),177177+ regmap_reg_range(BD96801_REG_PMIC_STATE, BD96801_REG_INT_BUCK2_ERRB),178178+ regmap_reg_range(BD96801_REG_INT_SYS_INTB, BD96801_REG_INT_BUCK2_INTB),179179+ /* Registers which do not update value unless PMIC is in STBY */180180+ regmap_reg_range(BD96801_REG_SSCG_CTRL, BD96801_REG_SHD_INTB),181181+ regmap_reg_range(BD96801_REG_BUCK_OVP, BD96801_REG_BOOT_OVERTIME),182182+};183183+184184+static const struct regmap_access_table bd96801_volatile_regs = {251185 .yes_ranges = bd96801_volatile_ranges,252186 .n_yes_ranges = ARRAY_SIZE(bd96801_volatile_ranges),187187+};188188+189189+static const struct regmap_access_table bd96802_volatile_regs = {190190+ .yes_ranges = bd96802_volatile_ranges,191191+ .n_yes_ranges = ARRAY_SIZE(bd96802_volatile_ranges),253192};254193255194/*···283188static unsigned int bit6_offsets[] = {8}; /* LDO 6 stat */284189static unsigned int bit7_offsets[] = {9}; /* LDO 7 stat */285190286286-static const struct regmap_irq_sub_irq_map errb_sub_irq_offsets[] = {191191+static const struct regmap_irq_sub_irq_map bd96801_errb_sub_irq_offsets[] = {287192 REGMAP_IRQ_MAIN_REG_OFFSET(bit0_offsets),288193 REGMAP_IRQ_MAIN_REG_OFFSET(bit1_offsets),289194 REGMAP_IRQ_MAIN_REG_OFFSET(bit2_offsets),···292197 REGMAP_IRQ_MAIN_REG_OFFSET(bit5_offsets),293198 REGMAP_IRQ_MAIN_REG_OFFSET(bit6_offsets),294199 REGMAP_IRQ_MAIN_REG_OFFSET(bit7_offsets),200200+};201201+202202+static const struct regmap_irq_sub_irq_map bd96802_errb_sub_irq_offsets[] = {203203+ REGMAP_IRQ_MAIN_REG_OFFSET(bit0_offsets),204204+ REGMAP_IRQ_MAIN_REG_OFFSET(bit1_offsets),205205+ REGMAP_IRQ_MAIN_REG_OFFSET(bit2_offsets),295206};296207297208static const struct regmap_irq bd96801_errb_irqs[] = {···360259 REGMAP_IRQ_REG(BD96801_LDO7_SHDN_ERR_STAT, 9, BD96801_OUT_SHDN_ERR_MASK),361260};362261262262+static const struct regmap_irq bd96802_errb_irqs[] = {263263+ /* Reg 0x52 Fatal ERRB1 */264264+ REGMAP_IRQ_REG(BD96802_OTP_ERR_STAT, 0, BD96801_OTP_ERR_MASK),265265+ REGMAP_IRQ_REG(BD96802_DBIST_ERR_STAT, 0, BD96801_DBIST_ERR_MASK),266266+ REGMAP_IRQ_REG(BD96802_EEP_ERR_STAT, 0, BD96801_EEP_ERR_MASK),267267+ REGMAP_IRQ_REG(BD96802_ABIST_ERR_STAT, 0, BD96801_ABIST_ERR_MASK),268268+ REGMAP_IRQ_REG(BD96802_PRSTB_ERR_STAT, 0, BD96801_PRSTB_ERR_MASK),269269+ REGMAP_IRQ_REG(BD96802_DRMOS1_ERR_STAT, 0, BD96801_DRMOS1_ERR_MASK),270270+ REGMAP_IRQ_REG(BD96802_DRMOS2_ERR_STAT, 0, BD96801_DRMOS2_ERR_MASK),271271+ REGMAP_IRQ_REG(BD96802_SLAVE_ERR_STAT, 0, BD96801_SLAVE_ERR_MASK),272272+ /* 0x53 Fatal ERRB2 */273273+ REGMAP_IRQ_REG(BD96802_VREF_ERR_STAT, 1, BD96801_VREF_ERR_MASK),274274+ REGMAP_IRQ_REG(BD96802_TSD_ERR_STAT, 1, BD96801_TSD_ERR_MASK),275275+ REGMAP_IRQ_REG(BD96802_UVLO_ERR_STAT, 1, BD96801_UVLO_ERR_MASK),276276+ REGMAP_IRQ_REG(BD96802_OVLO_ERR_STAT, 1, BD96801_OVLO_ERR_MASK),277277+ REGMAP_IRQ_REG(BD96802_OSC_ERR_STAT, 1, BD96801_OSC_ERR_MASK),278278+ REGMAP_IRQ_REG(BD96802_PON_ERR_STAT, 1, BD96801_PON_ERR_MASK),279279+ REGMAP_IRQ_REG(BD96802_POFF_ERR_STAT, 1, BD96801_POFF_ERR_MASK),280280+ REGMAP_IRQ_REG(BD96802_CMD_SHDN_ERR_STAT, 1, BD96801_CMD_SHDN_ERR_MASK),281281+ /* 0x54 Fatal INTB shadowed to ERRB */282282+ REGMAP_IRQ_REG(BD96802_INT_SHDN_ERR_STAT, 2, BD96801_INT_SHDN_ERR_MASK),283283+ /* Reg 0x55 BUCK1 ERR IRQs */284284+ REGMAP_IRQ_REG(BD96802_BUCK1_PVIN_ERR_STAT, 3, BD96801_OUT_PVIN_ERR_MASK),285285+ REGMAP_IRQ_REG(BD96802_BUCK1_OVP_ERR_STAT, 3, BD96801_OUT_OVP_ERR_MASK),286286+ REGMAP_IRQ_REG(BD96802_BUCK1_UVP_ERR_STAT, 3, BD96801_OUT_UVP_ERR_MASK),287287+ REGMAP_IRQ_REG(BD96802_BUCK1_SHDN_ERR_STAT, 3, BD96801_OUT_SHDN_ERR_MASK),288288+ /* Reg 0x56 BUCK2 ERR IRQs */289289+ REGMAP_IRQ_REG(BD96802_BUCK2_PVIN_ERR_STAT, 4, BD96801_OUT_PVIN_ERR_MASK),290290+ REGMAP_IRQ_REG(BD96802_BUCK2_OVP_ERR_STAT, 4, BD96801_OUT_OVP_ERR_MASK),291291+ REGMAP_IRQ_REG(BD96802_BUCK2_UVP_ERR_STAT, 4, BD96801_OUT_UVP_ERR_MASK),292292+ REGMAP_IRQ_REG(BD96802_BUCK2_SHDN_ERR_STAT, 4, BD96801_OUT_SHDN_ERR_MASK),293293+};294294+363295static const struct regmap_irq bd96801_intb_irqs[] = {364296 /* STATUS SYSTEM INTB */365297 REGMAP_IRQ_REG(BD96801_TW_STAT, 0, BD96801_TW_STAT_MASK),···441307 REGMAP_IRQ_REG(BD96801_LDO7_UVD_STAT, 7, BD96801_LDO_UVD_STAT_MASK),442308};443309310310+static const struct regmap_irq bd96802_intb_irqs[] = {311311+ /* STATUS SYSTEM INTB */312312+ REGMAP_IRQ_REG(BD96802_TW_STAT, 0, BD96801_TW_STAT_MASK),313313+ REGMAP_IRQ_REG(BD96802_WDT_ERR_STAT, 0, BD96801_WDT_ERR_STAT_MASK),314314+ REGMAP_IRQ_REG(BD96802_I2C_ERR_STAT, 0, BD96801_I2C_ERR_STAT_MASK),315315+ REGMAP_IRQ_REG(BD96802_CHIP_IF_ERR_STAT, 0, BD96801_CHIP_IF_ERR_STAT_MASK),316316+ /* STATUS BUCK1 INTB */317317+ REGMAP_IRQ_REG(BD96802_BUCK1_OCPH_STAT, 1, BD96801_BUCK_OCPH_STAT_MASK),318318+ REGMAP_IRQ_REG(BD96802_BUCK1_OCPL_STAT, 1, BD96801_BUCK_OCPL_STAT_MASK),319319+ REGMAP_IRQ_REG(BD96802_BUCK1_OCPN_STAT, 1, BD96801_BUCK_OCPN_STAT_MASK),320320+ REGMAP_IRQ_REG(BD96802_BUCK1_OVD_STAT, 1, BD96801_BUCK_OVD_STAT_MASK),321321+ REGMAP_IRQ_REG(BD96802_BUCK1_UVD_STAT, 1, BD96801_BUCK_UVD_STAT_MASK),322322+ REGMAP_IRQ_REG(BD96802_BUCK1_TW_CH_STAT, 1, BD96801_BUCK_TW_CH_STAT_MASK),323323+ /* BUCK 2 INTB */324324+ REGMAP_IRQ_REG(BD96802_BUCK2_OCPH_STAT, 2, BD96801_BUCK_OCPH_STAT_MASK),325325+ REGMAP_IRQ_REG(BD96802_BUCK2_OCPL_STAT, 2, BD96801_BUCK_OCPL_STAT_MASK),326326+ REGMAP_IRQ_REG(BD96802_BUCK2_OCPN_STAT, 2, BD96801_BUCK_OCPN_STAT_MASK),327327+ REGMAP_IRQ_REG(BD96802_BUCK2_OVD_STAT, 2, BD96801_BUCK_OVD_STAT_MASK),328328+ REGMAP_IRQ_REG(BD96802_BUCK2_UVD_STAT, 2, BD96801_BUCK_UVD_STAT_MASK),329329+ REGMAP_IRQ_REG(BD96802_BUCK2_TW_CH_STAT, 2, BD96801_BUCK_TW_CH_STAT_MASK),330330+};331331+332332+/*333333+ * The IRQ stuff is a bit hairy. The BD96801 / BD96802 provide two physical334334+ * IRQ lines called INTB and ERRB. They share the same main status register.335335+ *336336+ * For ERRB, mapping from main status to sub-status is such that the337337+ * 'global' faults are mapped to first 3 sub-status registers - and indicated338338+ * by the first bit[0] in main status reg.339339+ *340340+ * Rest of the status registers are for indicating stuff for individual341341+ * regulators, 1 sub register / regulator and 1 main status register bit /342342+ * regulator, starting from bit[1].343343+ *344344+ * Eg, regulator specific stuff has 1 to 1 mapping from main-status to sub345345+ * registers but 'global' ERRB IRQs require mapping from main status bit[0] to346346+ * 3 status registers.347347+ *348348+ * Furthermore, the BD96801 has 7 regulators where the BD96802 has only 2.349349+ *350350+ * INTB has only 1 sub status register for 'global' events and then own sub351351+ * status register for each of the regulators. So, for INTB we have direct352352+ * 1 to 1 mapping - BD96801 just having 5 register and 5 main status bits353353+ * more than the BD96802.354354+ *355355+ * Sharing the main status bits could be a problem if we had both INTB and356356+ * ERRB IRQs asserted but for different sub-status offsets. This might lead357357+ * IRQ controller code to go read a sub status register which indicates no358358+ * active IRQs. I assume this occurring repeteadly might lead the IRQ to be359359+ * disabled by core as a result of repeteadly returned IRQ_NONEs.360360+ *361361+ * I don't consider this as a fatal problem for now because:362362+ * a) Having ERRB asserted leads to PMIC fault state which will kill363363+ * the SoC powered by the PMIC. (So, relevant only for potential364364+ * case of not powering the processor with this PMIC).365365+ * b) Having ERRB set without having respective INTB is unlikely366366+ * (haven't actually verified this).367367+ *368368+ * So, let's proceed with main status enabled for both INTB and ERRB. We can369369+ * later disable main-status usage on systems where this ever proves to be370370+ * a problem.371371+ */372372+444373static const struct regmap_irq_chip bd96801_irq_chip_errb = {445374 .name = "bd96801-irq-errb",446375 .domain_suffix = "errb",···517320 .init_ack_masked = true,518321 .num_regs = 10,519322 .irq_reg_stride = 1,520520- .sub_reg_offsets = &errb_sub_irq_offsets[0],323323+ .sub_reg_offsets = &bd96801_errb_sub_irq_offsets[0],324324+};325325+326326+static const struct regmap_irq_chip bd96802_irq_chip_errb = {327327+ .name = "bd96802-irq-errb",328328+ .domain_suffix = "errb",329329+ .main_status = BD96801_REG_INT_MAIN,330330+ .num_main_regs = 1,331331+ .irqs = &bd96802_errb_irqs[0],332332+ .num_irqs = ARRAY_SIZE(bd96802_errb_irqs),333333+ .status_base = BD96801_REG_INT_SYS_ERRB1,334334+ .mask_base = BD96801_REG_MASK_SYS_ERRB,335335+ .ack_base = BD96801_REG_INT_SYS_ERRB1,336336+ .init_ack_masked = true,337337+ .num_regs = 5,338338+ .irq_reg_stride = 1,339339+ .sub_reg_offsets = &bd96802_errb_sub_irq_offsets[0],521340};522341523342static const struct regmap_irq_chip bd96801_irq_chip_intb = {···551338 .irq_reg_stride = 1,552339};553340341341+static const struct regmap_irq_chip bd96802_irq_chip_intb = {342342+ .name = "bd96802-irq-intb",343343+ .domain_suffix = "intb",344344+ .main_status = BD96801_REG_INT_MAIN,345345+ .num_main_regs = 1,346346+ .irqs = &bd96802_intb_irqs[0],347347+ .num_irqs = ARRAY_SIZE(bd96802_intb_irqs),348348+ .status_base = BD96801_REG_INT_SYS_INTB,349349+ .mask_base = BD96801_REG_MASK_SYS_INTB,350350+ .ack_base = BD96801_REG_INT_SYS_INTB,351351+ .init_ack_masked = true,352352+ .num_regs = 3,353353+ .irq_reg_stride = 1,354354+};355355+554356static const struct regmap_config bd96801_regmap_config = {555357 .reg_bits = 8,556358 .val_bits = 8,557557- .volatile_table = &volatile_regs,359359+ .volatile_table = &bd96801_volatile_regs,558360 .cache_type = REGCACHE_MAPLE,361361+};362362+363363+static const struct regmap_config bd96802_regmap_config = {364364+ .reg_bits = 8,365365+ .val_bits = 8,366366+ .volatile_table = &bd96802_volatile_regs,367367+ .cache_type = REGCACHE_MAPLE,368368+};369369+370370+static const struct bd968xx bd96801_data = {371371+ .errb_irqs = bd96801_reg_errb_irqs,372372+ .intb_irqs = bd96801_reg_intb_irqs,373373+ .num_errb_irqs = ARRAY_SIZE(bd96801_reg_errb_irqs),374374+ .num_intb_irqs = ARRAY_SIZE(bd96801_reg_intb_irqs),375375+ .errb_irq_chip = &bd96801_irq_chip_errb,376376+ .intb_irq_chip = &bd96801_irq_chip_intb,377377+ .regmap_config = &bd96801_regmap_config,378378+ .cells = bd96801_cells,379379+ .num_cells = ARRAY_SIZE(bd96801_cells),380380+ .unlock_reg = BD96801_LOCK_REG,381381+ .unlock_val = BD96801_UNLOCK,382382+};383383+384384+static const struct bd968xx bd96802_data = {385385+ .errb_irqs = bd96802_reg_errb_irqs,386386+ .intb_irqs = bd96802_reg_intb_irqs,387387+ .num_errb_irqs = ARRAY_SIZE(bd96802_reg_errb_irqs),388388+ .num_intb_irqs = ARRAY_SIZE(bd96802_reg_intb_irqs),389389+ .errb_irq_chip = &bd96802_irq_chip_errb,390390+ .intb_irq_chip = &bd96802_irq_chip_intb,391391+ .regmap_config = &bd96802_regmap_config,392392+ .cells = bd96802_cells,393393+ .num_cells = ARRAY_SIZE(bd96802_cells),394394+ .unlock_reg = BD96801_LOCK_REG,395395+ .unlock_val = BD96801_UNLOCK,396396+};397397+398398+static const struct bd968xx bd96805_data = {399399+ .errb_irqs = bd96801_reg_errb_irqs,400400+ .intb_irqs = bd96801_reg_intb_irqs,401401+ .num_errb_irqs = ARRAY_SIZE(bd96801_reg_errb_irqs),402402+ .num_intb_irqs = ARRAY_SIZE(bd96801_reg_intb_irqs),403403+ .errb_irq_chip = &bd96801_irq_chip_errb,404404+ .intb_irq_chip = &bd96801_irq_chip_intb,405405+ .regmap_config = &bd96801_regmap_config,406406+ .cells = bd96805_cells,407407+ .num_cells = ARRAY_SIZE(bd96805_cells),408408+ .unlock_reg = BD96801_LOCK_REG,409409+ .unlock_val = BD96801_UNLOCK,410410+};411411+412412+static struct bd968xx bd96806_data = {413413+ .errb_irqs = bd96802_reg_errb_irqs,414414+ .intb_irqs = bd96802_reg_intb_irqs,415415+ .num_errb_irqs = ARRAY_SIZE(bd96802_reg_errb_irqs),416416+ .num_intb_irqs = ARRAY_SIZE(bd96802_reg_intb_irqs),417417+ .errb_irq_chip = &bd96802_irq_chip_errb,418418+ .intb_irq_chip = &bd96802_irq_chip_intb,419419+ .regmap_config = &bd96802_regmap_config,420420+ .cells = bd96806_cells,421421+ .num_cells = ARRAY_SIZE(bd96806_cells),422422+ .unlock_reg = BD96801_LOCK_REG,423423+ .unlock_val = BD96801_UNLOCK,559424};560425561426static int bd96801_i2c_probe(struct i2c_client *i2c)562427{563428 struct regmap_irq_chip_data *intb_irq_data, *errb_irq_data;564429 struct irq_domain *intb_domain, *errb_domain;430430+ const struct bd968xx *ddata;565431 const struct fwnode_handle *fwnode;566432 struct resource *regulator_res;567433 struct resource wdg_irq;568434 struct regmap *regmap;569569- int intb_irq, errb_irq, num_intb, num_errb = 0;435435+ int intb_irq, errb_irq, num_errb = 0;570436 int num_regu_irqs, wdg_irq_no;437437+ unsigned int chip_type;571438 int i, ret;439439+440440+ chip_type = (unsigned int)(uintptr_t)device_get_match_data(&i2c->dev);441441+ switch (chip_type) {442442+ case ROHM_CHIP_TYPE_BD96801:443443+ ddata = &bd96801_data;444444+ break;445445+ case ROHM_CHIP_TYPE_BD96802:446446+ ddata = &bd96802_data;447447+ break;448448+ case ROHM_CHIP_TYPE_BD96805:449449+ ddata = &bd96805_data;450450+ break;451451+ case ROHM_CHIP_TYPE_BD96806:452452+ ddata = &bd96806_data;453453+ break;454454+ default:455455+ dev_err(&i2c->dev, "Unknown IC\n");456456+ return -EINVAL;457457+ }572458573459 fwnode = dev_fwnode(&i2c->dev);574460 if (!fwnode)···677365 if (intb_irq < 0)678366 return dev_err_probe(&i2c->dev, intb_irq, "INTB IRQ not configured\n");679367680680- num_intb = ARRAY_SIZE(regulator_intb_irqs);681681-682368 /* ERRB may be omitted if processor is powered by the PMIC */683369 errb_irq = fwnode_irq_get_byname(fwnode, "errb");684684- if (errb_irq < 0)685685- errb_irq = 0;370370+ if (errb_irq == -EPROBE_DEFER)371371+ return errb_irq;686372687687- if (errb_irq)688688- num_errb = ARRAY_SIZE(regulator_errb_irqs);373373+ if (errb_irq > 0)374374+ num_errb = ddata->num_errb_irqs;689375690690- num_regu_irqs = num_intb + num_errb;376376+ num_regu_irqs = ddata->num_intb_irqs + num_errb;691377692378 regulator_res = devm_kcalloc(&i2c->dev, num_regu_irqs,693379 sizeof(*regulator_res), GFP_KERNEL);694380 if (!regulator_res)695381 return -ENOMEM;696382697697- regmap = devm_regmap_init_i2c(i2c, &bd96801_regmap_config);383383+ regmap = devm_regmap_init_i2c(i2c, ddata->regmap_config);698384 if (IS_ERR(regmap))699385 return dev_err_probe(&i2c->dev, PTR_ERR(regmap),700386 "Regmap initialization failed\n");701387702702- ret = regmap_write(regmap, BD96801_LOCK_REG, BD96801_UNLOCK);388388+ ret = regmap_write(regmap, ddata->unlock_reg, ddata->unlock_val);703389 if (ret)704390 return dev_err_probe(&i2c->dev, ret, "Failed to unlock PMIC\n");705391706392 ret = devm_regmap_add_irq_chip(&i2c->dev, regmap, intb_irq,707707- IRQF_ONESHOT, 0, &bd96801_irq_chip_intb,393393+ IRQF_ONESHOT, 0, ddata->intb_irq_chip,708394 &intb_irq_data);709395 if (ret)710396 return dev_err_probe(&i2c->dev, ret, "Failed to add INTB IRQ chip\n");···714404 * has two domains so we do IRQ mapping here and provide the715405 * already mapped IRQ numbers to sub-devices.716406 */717717- for (i = 0; i < num_intb; i++) {407407+ for (i = 0; i < ddata->num_intb_irqs; i++) {718408 struct resource *res = ®ulator_res[i];719409720720- *res = regulator_intb_irqs[i];410410+ *res = ddata->intb_irqs[i];721411 res->start = res->end = irq_create_mapping(intb_domain,722412 res->start);723413 }724414725415 wdg_irq_no = irq_create_mapping(intb_domain, BD96801_WDT_ERR_STAT);726416 wdg_irq = DEFINE_RES_IRQ_NAMED(wdg_irq_no, "bd96801-wdg");727727- bd96801_cells[WDG_CELL].resources = &wdg_irq;728728- bd96801_cells[WDG_CELL].num_resources = 1;417417+418418+ ddata->cells[WDG_CELL].resources = &wdg_irq;419419+ ddata->cells[WDG_CELL].num_resources = 1;729420730421 if (!num_errb)731422 goto skip_errb;732423733424 ret = devm_regmap_add_irq_chip(&i2c->dev, regmap, errb_irq, IRQF_ONESHOT,734734- 0, &bd96801_irq_chip_errb, &errb_irq_data);425425+ 0, ddata->errb_irq_chip, &errb_irq_data);735426 if (ret)736427 return dev_err_probe(&i2c->dev, ret,737428 "Failed to add ERRB IRQ chip\n");···740429 errb_domain = regmap_irq_get_domain(errb_irq_data);741430742431 for (i = 0; i < num_errb; i++) {743743- struct resource *res = ®ulator_res[num_intb + i];432432+ struct resource *res = ®ulator_res[ddata->num_intb_irqs + i];744433745745- *res = regulator_errb_irqs[i];434434+ *res = ddata->errb_irqs[i];746435 res->start = res->end = irq_create_mapping(errb_domain, res->start);747436 }748437749438skip_errb:750750- bd96801_cells[REGULATOR_CELL].resources = regulator_res;751751- bd96801_cells[REGULATOR_CELL].num_resources = num_regu_irqs;752752-753753- ret = devm_mfd_add_devices(&i2c->dev, PLATFORM_DEVID_AUTO, bd96801_cells,754754- ARRAY_SIZE(bd96801_cells), NULL, 0, NULL);439439+ ddata->cells[REGULATOR_CELL].resources = regulator_res;440440+ ddata->cells[REGULATOR_CELL].num_resources = num_regu_irqs;441441+ ret = devm_mfd_add_devices(&i2c->dev, PLATFORM_DEVID_AUTO, ddata->cells,442442+ ddata->num_cells, NULL, 0, NULL);755443 if (ret)756444 dev_err_probe(&i2c->dev, ret, "Failed to create subdevices\n");757445···758448}759449760450static const struct of_device_id bd96801_of_match[] = {761761- { .compatible = "rohm,bd96801", },451451+ { .compatible = "rohm,bd96801", .data = (void *)ROHM_CHIP_TYPE_BD96801 },452452+ { .compatible = "rohm,bd96802", .data = (void *)ROHM_CHIP_TYPE_BD96802 },453453+ { .compatible = "rohm,bd96805", .data = (void *)ROHM_CHIP_TYPE_BD96805 },454454+ { .compatible = "rohm,bd96806", .data = (void *)ROHM_CHIP_TYPE_BD96806 },762455 { }763456};764457MODULE_DEVICE_TABLE(of, bd96801_of_match);···789476module_exit(bd96801_i2c_exit);790477791478MODULE_AUTHOR("Matti Vaittinen <matti.vaittinen@fi.rohmeurope.com>");792792-MODULE_DESCRIPTION("ROHM BD96801 Power Management IC driver");479479+MODULE_DESCRIPTION("ROHM BD9680X Power Management IC driver");793480MODULE_LICENSE("GPL");
+32-1
drivers/mfd/stm32-lptimer.c
···66 * Inspired by Benjamin Gaignard's stm32-timers driver77 */8899+#include <linux/bitfield.h>910#include <linux/mfd/stm32-lptimer.h>1011#include <linux/module.h>1112#include <linux/of_platform.h>···5049 return 0;5150}52515252+static int stm32_lptimer_detect_hwcfgr(struct stm32_lptimer *ddata)5353+{5454+ u32 val;5555+ int ret;5656+5757+ ret = regmap_read(ddata->regmap, STM32_LPTIM_VERR, &ddata->version);5858+ if (ret)5959+ return ret;6060+6161+ /* Try to guess parameters from HWCFGR: e.g. encoder mode (STM32MP15) */6262+ ret = regmap_read(ddata->regmap, STM32_LPTIM_HWCFGR1, &val);6363+ if (ret)6464+ return ret;6565+6666+ /* Fallback to legacy init if HWCFGR isn't present */6767+ if (!val)6868+ return stm32_lptimer_detect_encoder(ddata);6969+7070+ ddata->has_encoder = FIELD_GET(STM32_LPTIM_HWCFGR1_ENCODER, val);7171+7272+ ret = regmap_read(ddata->regmap, STM32_LPTIM_HWCFGR2, &val);7373+ if (ret)7474+ return ret;7575+7676+ /* Number of capture/compare channels */7777+ ddata->num_cc_chans = FIELD_GET(STM32_LPTIM_HWCFGR2_CHAN_NUM, val);7878+7979+ return 0;8080+}8181+5382static int stm32_lptimer_probe(struct platform_device *pdev)5483{5584 struct device *dev = &pdev->dev;···10473 if (IS_ERR(ddata->clk))10574 return PTR_ERR(ddata->clk);10675107107- ret = stm32_lptimer_detect_encoder(ddata);7676+ ret = stm32_lptimer_detect_hwcfgr(ddata);10877 if (ret)10978 return ret;11079
+12
drivers/nvmem/Kconfig
···154154 To compile this driver as a module, choose M here: the module155155 will be called nvmem_lpc18xx_otp.156156157157+config NVMEM_MAX77759158158+ tristate "Maxim Integrated MAX77759 NVMEM Support"159159+ depends on MFD_MAX77759160160+ default MFD_MAX77759161161+ help162162+ Say Y here to include support for the user-accessible storage found163163+ in Maxim Integrated MAX77759 PMICs. This IC provides space for 30164164+ bytes of storage.165165+166166+ This driver can also be built as a module. If so, the module167167+ will be called nvmem-max77759.168168+157169config NVMEM_MESON_EFUSE158170 tristate "Amlogic Meson GX eFuse Support"159171 depends on (ARCH_MESON || COMPILE_TEST) && MESON_SM