Commit 04f38933 authored by Lee Jones's avatar Lee Jones

Merge branch 'ib-mfd-regulator-pm8008-6.11' into ibs-for-mfd-merged

parents 5ffe70d8 11d861d2
...@@ -19,110 +19,136 @@ properties: ...@@ -19,110 +19,136 @@ properties:
const: qcom,pm8008 const: qcom,pm8008
reg: reg:
description:
I2C slave address.
maxItems: 1 maxItems: 1
interrupts: interrupts:
maxItems: 1 maxItems: 1
description: Parent interrupt. reset-gpios:
maxItems: 1
vdd-l1-l2-supply: true
vdd-l3-l4-supply: true
vdd-l5-supply: true
vdd-l6-supply: true
vdd-l7-supply: true
"#interrupt-cells": gpio-controller: true
"#gpio-cells":
const: 2 const: 2
description: | gpio-ranges:
The first cell is the IRQ number, the second cell is the IRQ trigger maxItems: 1
flag. All interrupts are listed in include/dt-bindings/mfd/qcom-pm8008.h.
interrupt-controller: true interrupt-controller: true
"#address-cells": "#interrupt-cells":
const: 1 const: 2
"#size-cells": "#thermal-sensor-cells":
const: 0 const: 0
patternProperties: pinctrl:
"^gpio@[0-9a-f]+$": type: object
additionalProperties: false
patternProperties:
"-state$":
type: object type: object
description: | allOf:
The GPIO peripheral. This node may be specified twice, one for each GPIO. - $ref: /schemas/pinctrl/pinmux-node.yaml
- $ref: /schemas/pinctrl/pincfg-node.yaml
properties: properties:
compatible: pins:
items: items:
- const: qcom,pm8008-gpio pattern: "^gpio[12]$"
- const: qcom,spmi-gpio
reg: function:
description: Peripheral address of one of the two GPIO peripherals. items:
maxItems: 1 - enum:
- normal
gpio-controller: true
gpio-ranges:
maxItems: 1
interrupt-controller: true
"#interrupt-cells":
const: 2
"#gpio-cells":
const: 2
required: required:
- compatible - pins
- reg - function
- gpio-controller
- interrupt-controller
- "#gpio-cells"
- gpio-ranges
- "#interrupt-cells"
additionalProperties: false additionalProperties: false
regulators:
type: object
additionalProperties: false
patternProperties:
"^ldo[1-7]$":
type: object
$ref: /schemas/regulator/regulator.yaml#
unevaluatedProperties: false
required: required:
- compatible - compatible
- reg - reg
- interrupts - interrupts
- "#address-cells" - vdd-l1-l2-supply
- "#size-cells" - vdd-l3-l4-supply
- vdd-l5-supply
- vdd-l6-supply
- vdd-l7-supply
- gpio-controller
- "#gpio-cells"
- gpio-ranges
- interrupt-controller
- "#interrupt-cells" - "#interrupt-cells"
- "#thermal-sensor-cells"
additionalProperties: false additionalProperties: false
examples: examples:
- | - |
#include <dt-bindings/mfd/qcom-pm8008.h> #include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/interrupt-controller/irq.h> #include <dt-bindings/interrupt-controller/irq.h>
i2c { i2c {
#address-cells = <1>; #address-cells = <1>;
#size-cells = <0>; #size-cells = <0>;
pmic@8 { pm8008: pmic@8 {
compatible = "qcom,pm8008"; compatible = "qcom,pm8008";
reg = <0x8>; reg = <0x8>;
#address-cells = <1>;
#size-cells = <0>;
interrupt-controller;
#interrupt-cells = <2>;
interrupt-parent = <&tlmm>; interrupt-parent = <&tlmm>;
interrupts = <32 IRQ_TYPE_EDGE_RISING>; interrupts = <32 IRQ_TYPE_EDGE_RISING>;
pm8008_gpios: gpio@c000 { reset-gpios = <&tlmm 42 GPIO_ACTIVE_LOW>;
compatible = "qcom,pm8008-gpio", "qcom,spmi-gpio";
reg = <0xc000>; vdd-l1-l2-supply = <&vreg_s8b_1p2>;
vdd-l3-l4-supply = <&vreg_s1b_1p8>;
vdd-l5-supply = <&vreg_bob>;
vdd-l6-supply = <&vreg_bob>;
vdd-l7-supply = <&vreg_bob>;
gpio-controller; gpio-controller;
gpio-ranges = <&pm8008_gpios 0 0 2>;
#gpio-cells = <2>; #gpio-cells = <2>;
gpio-ranges = <&pm8008 0 0 2>;
interrupt-controller; interrupt-controller;
#interrupt-cells = <2>; #interrupt-cells = <2>;
#thermal-sensor-cells = <0>;
pinctrl {
gpio-keys-state {
pins = "gpio1";
function = "normal";
};
};
regulators {
ldo1 {
regulator-name = "vreg_l1";
regulator-min-microvolt = <950000>;
regulator-max-microvolt = <1300000>;
};
}; };
}; };
}; };
......
...@@ -2220,6 +2220,7 @@ config MFD_ACER_A500_EC ...@@ -2220,6 +2220,7 @@ config MFD_ACER_A500_EC
config MFD_QCOM_PM8008 config MFD_QCOM_PM8008
tristate "QCOM PM8008 Power Management IC" tristate "QCOM PM8008 Power Management IC"
depends on I2C && OF depends on I2C && OF
select MFD_CORE
select REGMAP_I2C select REGMAP_I2C
select REGMAP_IRQ select REGMAP_IRQ
help help
......
...@@ -4,10 +4,13 @@ ...@@ -4,10 +4,13 @@
*/ */
#include <linux/bitops.h> #include <linux/bitops.h>
#include <linux/gpio/consumer.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/ioport.h>
#include <linux/irq.h> #include <linux/irq.h>
#include <linux/irqdomain.h> #include <linux/irqdomain.h>
#include <linux/mfd/core.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/of.h> #include <linux/of.h>
#include <linux/of_platform.h> #include <linux/of_platform.h>
...@@ -15,8 +18,6 @@ ...@@ -15,8 +18,6 @@
#include <linux/regmap.h> #include <linux/regmap.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <dt-bindings/mfd/qcom-pm8008.h>
#define I2C_INTR_STATUS_BASE 0x0550 #define I2C_INTR_STATUS_BASE 0x0550
#define INT_RT_STS_OFFSET 0x10 #define INT_RT_STS_OFFSET 0x10
#define INT_SET_TYPE_OFFSET 0x11 #define INT_SET_TYPE_OFFSET 0x11
...@@ -37,34 +38,54 @@ enum { ...@@ -37,34 +38,54 @@ enum {
#define PM8008_PERIPH_0_BASE 0x900 #define PM8008_PERIPH_0_BASE 0x900
#define PM8008_PERIPH_1_BASE 0x2400 #define PM8008_PERIPH_1_BASE 0x2400
#define PM8008_PERIPH_2_BASE 0xC000 #define PM8008_PERIPH_2_BASE 0xc000
#define PM8008_PERIPH_3_BASE 0xC100 #define PM8008_PERIPH_3_BASE 0xc100
#define PM8008_TEMP_ALARM_ADDR PM8008_PERIPH_1_BASE #define PM8008_TEMP_ALARM_ADDR PM8008_PERIPH_1_BASE
#define PM8008_GPIO1_ADDR PM8008_PERIPH_2_BASE #define PM8008_GPIO1_ADDR PM8008_PERIPH_2_BASE
#define PM8008_GPIO2_ADDR PM8008_PERIPH_3_BASE #define PM8008_GPIO2_ADDR PM8008_PERIPH_3_BASE
/* PM8008 IRQ numbers */
#define PM8008_IRQ_MISC_UVLO 0
#define PM8008_IRQ_MISC_OVLO 1
#define PM8008_IRQ_MISC_OTST2 2
#define PM8008_IRQ_MISC_OTST3 3
#define PM8008_IRQ_MISC_LDO_OCP 4
#define PM8008_IRQ_TEMP_ALARM 5
#define PM8008_IRQ_GPIO1 6
#define PM8008_IRQ_GPIO2 7
enum { enum {
SET_TYPE_INDEX, SET_TYPE_INDEX,
POLARITY_HI_INDEX, POLARITY_HI_INDEX,
POLARITY_LO_INDEX, POLARITY_LO_INDEX,
}; };
static unsigned int pm8008_config_regs[] = { static const unsigned int pm8008_config_regs[] = {
INT_SET_TYPE_OFFSET, INT_SET_TYPE_OFFSET,
INT_POL_HIGH_OFFSET, INT_POL_HIGH_OFFSET,
INT_POL_LOW_OFFSET, INT_POL_LOW_OFFSET,
}; };
static struct regmap_irq pm8008_irqs[] = { #define _IRQ(_irq, _off, _mask, _types) \
REGMAP_IRQ_REG(PM8008_IRQ_MISC_UVLO, PM8008_MISC, BIT(0)), [_irq] = { \
REGMAP_IRQ_REG(PM8008_IRQ_MISC_OVLO, PM8008_MISC, BIT(1)), .reg_offset = (_off), \
REGMAP_IRQ_REG(PM8008_IRQ_MISC_OTST2, PM8008_MISC, BIT(2)), .mask = (_mask), \
REGMAP_IRQ_REG(PM8008_IRQ_MISC_OTST3, PM8008_MISC, BIT(3)), .type = { \
REGMAP_IRQ_REG(PM8008_IRQ_MISC_LDO_OCP, PM8008_MISC, BIT(4)), .type_reg_offset = (_off), \
REGMAP_IRQ_REG(PM8008_IRQ_TEMP_ALARM, PM8008_TEMP_ALARM, BIT(0)), .types_supported = (_types), \
REGMAP_IRQ_REG(PM8008_IRQ_GPIO1, PM8008_GPIO1, BIT(0)), }, \
REGMAP_IRQ_REG(PM8008_IRQ_GPIO2, PM8008_GPIO2, BIT(0)), }
static const struct regmap_irq pm8008_irqs[] = {
_IRQ(PM8008_IRQ_MISC_UVLO, PM8008_MISC, BIT(0), IRQ_TYPE_EDGE_RISING),
_IRQ(PM8008_IRQ_MISC_OVLO, PM8008_MISC, BIT(1), IRQ_TYPE_EDGE_RISING),
_IRQ(PM8008_IRQ_MISC_OTST2, PM8008_MISC, BIT(2), IRQ_TYPE_EDGE_RISING),
_IRQ(PM8008_IRQ_MISC_OTST3, PM8008_MISC, BIT(3), IRQ_TYPE_EDGE_RISING),
_IRQ(PM8008_IRQ_MISC_LDO_OCP, PM8008_MISC, BIT(4), IRQ_TYPE_EDGE_RISING),
_IRQ(PM8008_IRQ_TEMP_ALARM, PM8008_TEMP_ALARM,BIT(0), IRQ_TYPE_SENSE_MASK),
_IRQ(PM8008_IRQ_GPIO1, PM8008_GPIO1, BIT(0), IRQ_TYPE_SENSE_MASK),
_IRQ(PM8008_IRQ_GPIO2, PM8008_GPIO2, BIT(0), IRQ_TYPE_SENSE_MASK),
}; };
static const unsigned int pm8008_periph_base[] = { static const unsigned int pm8008_periph_base[] = {
...@@ -118,8 +139,8 @@ static int pm8008_set_type_config(unsigned int **buf, unsigned int type, ...@@ -118,8 +139,8 @@ static int pm8008_set_type_config(unsigned int **buf, unsigned int type,
return 0; return 0;
} }
static struct regmap_irq_chip pm8008_irq_chip = { static const struct regmap_irq_chip pm8008_irq_chip = {
.name = "pm8008_irq", .name = "pm8008",
.main_status = I2C_INTR_STATUS_BASE, .main_status = I2C_INTR_STATUS_BASE,
.num_main_regs = 1, .num_main_regs = 1,
.irqs = pm8008_irqs, .irqs = pm8008_irqs,
...@@ -137,62 +158,106 @@ static struct regmap_irq_chip pm8008_irq_chip = { ...@@ -137,62 +158,106 @@ static struct regmap_irq_chip pm8008_irq_chip = {
.get_irq_reg = pm8008_get_irq_reg, .get_irq_reg = pm8008_get_irq_reg,
}; };
static struct regmap_config qcom_mfd_regmap_cfg = { static const struct regmap_config qcom_mfd_regmap_cfg = {
.name = "primary",
.reg_bits = 16, .reg_bits = 16,
.val_bits = 8, .val_bits = 8,
.max_register = 0xFFFF, .max_register = 0xffff,
}; };
static int pm8008_probe_irq_peripherals(struct device *dev, static const struct regmap_config pm8008_regmap_cfg_2 = {
struct regmap *regmap, .name = "secondary",
int client_irq) .reg_bits = 16,
{ .val_bits = 8,
int rc, i; .max_register = 0xffff,
struct regmap_irq_type *type; };
struct regmap_irq_chip_data *irq_data;
for (i = 0; i < ARRAY_SIZE(pm8008_irqs); i++) {
type = &pm8008_irqs[i].type;
type->type_reg_offset = pm8008_irqs[i].reg_offset; static const struct resource pm8008_temp_res[] = {
DEFINE_RES_MEM(PM8008_TEMP_ALARM_ADDR, 0x100),
DEFINE_RES_IRQ(PM8008_IRQ_TEMP_ALARM),
};
if (type->type_reg_offset == PM8008_MISC) static const struct mfd_cell pm8008_cells[] = {
type->types_supported = IRQ_TYPE_EDGE_RISING; MFD_CELL_NAME("pm8008-regulator"),
else MFD_CELL_RES("qpnp-temp-alarm", pm8008_temp_res),
type->types_supported = (IRQ_TYPE_EDGE_BOTH | MFD_CELL_NAME("pm8008-gpio"),
IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW); };
}
rc = devm_regmap_add_irq_chip(dev, regmap, client_irq, static void devm_irq_domain_fwnode_release(void *data)
IRQF_SHARED, 0, &pm8008_irq_chip, &irq_data); {
if (rc) { struct fwnode_handle *fwnode = data;
dev_err(dev, "Failed to add IRQ chip: %d\n", rc);
return rc;
}
return 0; irq_domain_free_fwnode(fwnode);
} }
static int pm8008_probe(struct i2c_client *client) static int pm8008_probe(struct i2c_client *client)
{ {
int rc; struct regmap_irq_chip_data *irq_data;
struct device *dev; struct device *dev = &client->dev;
struct regmap *regmap; struct regmap *regmap, *regmap2;
struct fwnode_handle *fwnode;
struct i2c_client *dummy;
struct gpio_desc *reset;
char *name;
int ret;
dummy = devm_i2c_new_dummy_device(dev, client->adapter, client->addr + 1);
if (IS_ERR(dummy)) {
ret = PTR_ERR(dummy);
dev_err(dev, "failed to claim second address: %d\n", ret);
return ret;
}
regmap2 = devm_regmap_init_i2c(dummy, &qcom_mfd_regmap_cfg);
if (IS_ERR(regmap2))
return PTR_ERR(regmap2);
dev = &client->dev; ret = regmap_attach_dev(dev, regmap2, &pm8008_regmap_cfg_2);
if (ret)
return ret;
/* Default regmap must be attached last. */
regmap = devm_regmap_init_i2c(client, &qcom_mfd_regmap_cfg); regmap = devm_regmap_init_i2c(client, &qcom_mfd_regmap_cfg);
if (IS_ERR(regmap)) if (IS_ERR(regmap))
return PTR_ERR(regmap); return PTR_ERR(regmap);
i2c_set_clientdata(client, regmap); reset = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW);
if (IS_ERR(reset))
return PTR_ERR(reset);
if (of_property_read_bool(dev->of_node, "interrupt-controller")) { /*
rc = pm8008_probe_irq_peripherals(dev, regmap, client->irq); * The PMIC does not appear to require a post-reset delay, but wait
if (rc) * for a millisecond for now anyway.
dev_err(dev, "Failed to probe irq periphs: %d\n", rc); */
usleep_range(1000, 2000);
name = devm_kasprintf(dev, GFP_KERNEL, "%pOF-internal", dev->of_node);
if (!name)
return -ENOMEM;
name = strreplace(name, '/', ':');
fwnode = irq_domain_alloc_named_fwnode(name);
if (!fwnode)
return -ENOMEM;
ret = devm_add_action_or_reset(dev, devm_irq_domain_fwnode_release, fwnode);
if (ret)
return ret;
ret = devm_regmap_add_irq_chip_fwnode(dev, fwnode, regmap, client->irq,
IRQF_SHARED, 0, &pm8008_irq_chip, &irq_data);
if (ret) {
dev_err(dev, "failed to add IRQ chip: %d\n", ret);
return ret;
} }
return devm_of_platform_populate(dev); /* Needed by GPIO driver. */
dev_set_drvdata(dev, regmap_irq_get_domain(irq_data));
return devm_mfd_add_devices(dev, PLATFORM_DEVID_AUTO, pm8008_cells,
ARRAY_SIZE(pm8008_cells), NULL, 0,
regmap_irq_get_domain(irq_data));
} }
static const struct of_device_id pm8008_match[] = { static const struct of_device_id pm8008_match[] = {
......
...@@ -1033,6 +1033,13 @@ config REGULATOR_PWM ...@@ -1033,6 +1033,13 @@ config REGULATOR_PWM
This driver supports PWM controlled voltage regulators. PWM This driver supports PWM controlled voltage regulators. PWM
duty cycle can increase or decrease the voltage. duty cycle can increase or decrease the voltage.
config REGULATOR_QCOM_PM8008
tristate "Qualcomm PM8008 PMIC regulators"
depends on MFD_QCOM_PM8008
help
Select this option to enable support for the voltage regulators in
Qualcomm PM8008 PMICs.
config REGULATOR_QCOM_REFGEN config REGULATOR_QCOM_REFGEN
tristate "Qualcomm REFGEN regulator driver" tristate "Qualcomm REFGEN regulator driver"
depends on ARCH_QCOM || COMPILE_TEST depends on ARCH_QCOM || COMPILE_TEST
......
...@@ -113,6 +113,7 @@ obj-$(CONFIG_REGULATOR_MT6380) += mt6380-regulator.o ...@@ -113,6 +113,7 @@ obj-$(CONFIG_REGULATOR_MT6380) += mt6380-regulator.o
obj-$(CONFIG_REGULATOR_MT6397) += mt6397-regulator.o obj-$(CONFIG_REGULATOR_MT6397) += mt6397-regulator.o
obj-$(CONFIG_REGULATOR_MTK_DVFSRC) += mtk-dvfsrc-regulator.o obj-$(CONFIG_REGULATOR_MTK_DVFSRC) += mtk-dvfsrc-regulator.o
obj-$(CONFIG_REGULATOR_QCOM_LABIBB) += qcom-labibb-regulator.o obj-$(CONFIG_REGULATOR_QCOM_LABIBB) += qcom-labibb-regulator.o
obj-$(CONFIG_REGULATOR_QCOM_PM8008) += qcom-pm8008-regulator.o
obj-$(CONFIG_REGULATOR_QCOM_REFGEN) += qcom-refgen-regulator.o obj-$(CONFIG_REGULATOR_QCOM_REFGEN) += qcom-refgen-regulator.o
obj-$(CONFIG_REGULATOR_QCOM_RPM) += qcom_rpm-regulator.o obj-$(CONFIG_REGULATOR_QCOM_RPM) += qcom_rpm-regulator.o
obj-$(CONFIG_REGULATOR_QCOM_RPMH) += qcom-rpmh-regulator.o obj-$(CONFIG_REGULATOR_QCOM_RPMH) += qcom-rpmh-regulator.o
......
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2019-2020, The Linux Foundation. All rights reserved.
* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
* Copyright (c) 2024 Linaro Limited
*/
#include <linux/array_size.h>
#include <linux/bits.h>
#include <linux/device.h>
#include <linux/math.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
#include <linux/regulator/driver.h>
#include <asm/byteorder.h>
#define DEFAULT_VOLTAGE_STEPPER_RATE 38400
#define LDO_STEPPER_CTL_REG 0x3b
#define STEP_RATE_MASK GENMASK(1, 0)
#define LDO_VSET_LB_REG 0x40
#define LDO_ENABLE_REG 0x46
#define ENABLE_BIT BIT(7)
struct pm8008_regulator {
struct regmap *regmap;
struct regulator_desc desc;
unsigned int base;
};
struct pm8008_regulator_data {
const char *name;
const char *supply_name;
unsigned int base;
int min_dropout_uV;
const struct linear_range *voltage_range;
};
static const struct linear_range nldo_ranges[] = {
REGULATOR_LINEAR_RANGE(528000, 0, 122, 8000),
};
static const struct linear_range pldo_ranges[] = {
REGULATOR_LINEAR_RANGE(1504000, 0, 237, 8000),
};
static const struct pm8008_regulator_data pm8008_reg_data[] = {
{ "ldo1", "vdd-l1-l2", 0x4000, 225000, nldo_ranges, },
{ "ldo2", "vdd-l1-l2", 0x4100, 225000, nldo_ranges, },
{ "ldo3", "vdd-l3-l4", 0x4200, 300000, pldo_ranges, },
{ "ldo4", "vdd-l3-l4", 0x4300, 300000, pldo_ranges, },
{ "ldo5", "vdd-l5", 0x4400, 200000, pldo_ranges, },
{ "ldo6", "vdd-l6", 0x4500, 200000, pldo_ranges, },
{ "ldo7", "vdd-l7", 0x4600, 200000, pldo_ranges, },
};
static int pm8008_regulator_set_voltage_sel(struct regulator_dev *rdev, unsigned int sel)
{
struct pm8008_regulator *preg = rdev_get_drvdata(rdev);
unsigned int mV;
__le16 val;
int ret;
ret = regulator_list_voltage_linear_range(rdev, sel);
if (ret < 0)
return ret;
mV = DIV_ROUND_UP(ret, 1000);
val = cpu_to_le16(mV);
ret = regmap_bulk_write(preg->regmap, preg->base + LDO_VSET_LB_REG,
&val, sizeof(val));
if (ret < 0)
return ret;
return 0;
}
static int pm8008_regulator_get_voltage_sel(struct regulator_dev *rdev)
{
struct pm8008_regulator *preg = rdev_get_drvdata(rdev);
unsigned int uV;
__le16 val;
int ret;
ret = regmap_bulk_read(preg->regmap, preg->base + LDO_VSET_LB_REG,
&val, sizeof(val));
if (ret < 0)
return ret;
uV = le16_to_cpu(val) * 1000;
return (uV - preg->desc.min_uV) / preg->desc.uV_step;
}
static const struct regulator_ops pm8008_regulator_ops = {
.list_voltage = regulator_list_voltage_linear,
.set_voltage_sel = pm8008_regulator_set_voltage_sel,
.get_voltage_sel = pm8008_regulator_get_voltage_sel,
.enable = regulator_enable_regmap,
.disable = regulator_disable_regmap,
.is_enabled = regulator_is_enabled_regmap,
};
static int pm8008_regulator_probe(struct platform_device *pdev)
{
const struct pm8008_regulator_data *data;
struct regulator_config config = {};
struct device *dev = &pdev->dev;
struct pm8008_regulator *preg;
struct regulator_desc *desc;
struct regulator_dev *rdev;
struct regmap *regmap;
unsigned int val;
int ret, i;
regmap = dev_get_regmap(dev->parent, "secondary");
if (!regmap)
return -EINVAL;
for (i = 0; i < ARRAY_SIZE(pm8008_reg_data); i++) {
data = &pm8008_reg_data[i];
preg = devm_kzalloc(dev, sizeof(*preg), GFP_KERNEL);
if (!preg)
return -ENOMEM;
preg->regmap = regmap;
preg->base = data->base;
desc = &preg->desc;
desc->name = data->name;
desc->supply_name = data->supply_name;
desc->of_match = data->name;
desc->regulators_node = of_match_ptr("regulators");
desc->ops = &pm8008_regulator_ops;
desc->type = REGULATOR_VOLTAGE;
desc->owner = THIS_MODULE;
desc->linear_ranges = data->voltage_range;
desc->n_linear_ranges = 1;
desc->uV_step = desc->linear_ranges[0].step;
desc->min_uV = desc->linear_ranges[0].min;
desc->n_voltages = linear_range_values_in_range(&desc->linear_ranges[0]);
ret = regmap_read(regmap, preg->base + LDO_STEPPER_CTL_REG, &val);
if (ret < 0) {
dev_err(dev, "failed to read step rate: %d\n", ret);
return ret;
}
val &= STEP_RATE_MASK;
desc->ramp_delay = DEFAULT_VOLTAGE_STEPPER_RATE >> val;
desc->min_dropout_uV = data->min_dropout_uV;
desc->enable_reg = preg->base + LDO_ENABLE_REG;
desc->enable_mask = ENABLE_BIT;
config.dev = dev->parent;
config.driver_data = preg;
config.regmap = regmap;
rdev = devm_regulator_register(dev, desc, &config);
if (IS_ERR(rdev)) {
ret = PTR_ERR(rdev);
dev_err(dev, "failed to register regulator %s: %d\n",
desc->name, ret);
return ret;
}
}
return 0;
}
static const struct platform_device_id pm8008_regulator_id_table[] = {
{ "pm8008-regulator" },
{ }
};
MODULE_DEVICE_TABLE(platform, pm8008_regulator_id_table);
static struct platform_driver pm8008_regulator_driver = {
.driver = {
.name = "qcom-pm8008-regulator",
},
.probe = pm8008_regulator_probe,
.id_table = pm8008_regulator_id_table,
};
module_platform_driver(pm8008_regulator_driver);
MODULE_DESCRIPTION("Qualcomm PM8008 PMIC regulator driver");
MODULE_LICENSE("GPL");
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (c) 2021 The Linux Foundation. All rights reserved.
*/
#ifndef __DT_BINDINGS_MFD_QCOM_PM8008_H
#define __DT_BINDINGS_MFD_QCOM_PM8008_H
/* PM8008 IRQ numbers */
#define PM8008_IRQ_MISC_UVLO 0
#define PM8008_IRQ_MISC_OVLO 1
#define PM8008_IRQ_MISC_OTST2 2
#define PM8008_IRQ_MISC_OTST3 3
#define PM8008_IRQ_MISC_LDO_OCP 4
#define PM8008_IRQ_TEMP_ALARM 5
#define PM8008_IRQ_GPIO1 6
#define PM8008_IRQ_GPIO2 7
#endif
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment