Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
linux
Commits
04f38933
Commit
04f38933
authored
Jul 04, 2024
by
Lee Jones
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'ib-mfd-regulator-pm8008-6.11' into ibs-for-mfd-merged
parents
5ffe70d8
11d861d2
Changes
7
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
409 additions
and
130 deletions
+409
-130
Documentation/devicetree/bindings/mfd/qcom,pm8008.yaml
Documentation/devicetree/bindings/mfd/qcom,pm8008.yaml
+85
-59
drivers/mfd/Kconfig
drivers/mfd/Kconfig
+1
-0
drivers/mfd/qcom-pm8008.c
drivers/mfd/qcom-pm8008.c
+117
-52
drivers/regulator/Kconfig
drivers/regulator/Kconfig
+7
-0
drivers/regulator/Makefile
drivers/regulator/Makefile
+1
-0
drivers/regulator/qcom-pm8008-regulator.c
drivers/regulator/qcom-pm8008-regulator.c
+198
-0
include/dt-bindings/mfd/qcom-pm8008.h
include/dt-bindings/mfd/qcom-pm8008.h
+0
-19
No files found.
Documentation/devicetree/bindings/mfd/qcom,pm8008.yaml
View file @
04f38933
...
...
@@ -19,110 +19,136 @@ properties:
const
:
qcom,pm8008
reg
:
description
:
I2C slave address.
maxItems
:
1
interrupts
:
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
description
:
|
The first cell is the IRQ number, the second cell is the IRQ trigger
flag. All interrupts are listed in include/dt-bindings/mfd/qcom-pm8008.h.
gpio-ranges
:
maxItems
:
1
interrupt-controller
:
true
"
#
address
-cells"
:
const
:
1
"
#
interrupt
-cells"
:
const
:
2
"
#
size
-cells"
:
"
#
thermal-sensor
-cells"
:
const
:
0
patternProperties
:
"
^gpio@[0-9a-f]+$"
:
pinctrl
:
type
:
object
additionalProperties
:
false
patternProperties
:
"
-state$"
:
type
:
object
description
:
|
The GPIO peripheral. This node may be specified twice, one for each GPIO.
properties
:
compatible
:
items
:
-
const
:
qcom,pm8008-gpio
-
const
:
qcom,spmi-gpio
reg
:
description
:
Peripheral address of one of the two GPIO peripherals.
maxItems
:
1
gpio-controller
:
true
gpio-ranges
:
maxItems
:
1
allOf
:
-
$ref
:
/schemas/pinctrl/pinmux-node.yaml
-
$ref
:
/schemas/pinctrl/pincfg-node.yaml
interrupt-controller
:
true
properties
:
pins
:
items
:
pattern
:
"
^gpio[12]$"
"
#interrupt-cells"
:
const
:
2
function
:
items
:
-
enum
:
-
normal
"
#gpio-cells"
:
const
:
2
required
:
-
pins
-
function
required
:
-
compatible
-
reg
-
gpio-controller
-
interrupt-controller
-
"
#gpio-cells"
-
gpio-ranges
-
"
#interrupt-cells"
additionalProperties
:
false
regulators
:
type
:
object
additionalProperties
:
false
patternProperties
:
"
^ldo[1-7]$"
:
type
:
object
$ref
:
/schemas/regulator/regulator.yaml#
unevaluatedProperties
:
false
required
:
-
compatible
-
reg
-
interrupts
-
"
#address-cells"
-
"
#size-cells"
-
vdd-l1-l2-supply
-
vdd-l3-l4-supply
-
vdd-l5-supply
-
vdd-l6-supply
-
vdd-l7-supply
-
gpio-controller
-
"
#gpio-cells"
-
gpio-ranges
-
interrupt-controller
-
"
#interrupt-cells"
-
"
#thermal-sensor-cells"
additionalProperties
:
false
examples
:
-
|
#include <dt-bindings/
mfd/qcom-pm8008
.h>
#include <dt-bindings/
gpio/gpio
.h>
#include <dt-bindings/interrupt-controller/irq.h>
i2c {
#address-cells = <1>;
#size-cells = <0>;
pmic@8 {
pm
8008: pm
ic@8 {
compatible = "qcom,pm8008";
reg = <0x8>;
#address-cells = <1>;
#size-cells = <0>;
interrupt-controller;
#interrupt-cells = <2>;
interrupt-parent = <&tlmm>;
interrupts = <32 IRQ_TYPE_EDGE_RISING>;
pm8008_gpios: gpio@c000 {
compatible = "qcom,pm8008-gpio", "qcom,spmi-gpio";
reg = <0xc000>;
gpio-controller;
gpio-ranges = <&pm8008_gpios 0 0 2>;
#gpio-cells = <2>;
interrupt-controller;
#interrupt-cells = <2>;
reset-gpios = <&tlmm 42 GPIO_ACTIVE_LOW>;
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-cells = <2>;
gpio-ranges = <&pm8008 0 0 2>;
interrupt-controller;
#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>;
};
};
};
};
...
...
drivers/mfd/Kconfig
View file @
04f38933
...
...
@@ -2220,6 +2220,7 @@ config MFD_ACER_A500_EC
config MFD_QCOM_PM8008
tristate "QCOM PM8008 Power Management IC"
depends on I2C && OF
select MFD_CORE
select REGMAP_I2C
select REGMAP_IRQ
help
...
...
drivers/mfd/qcom-pm8008.c
View file @
04f38933
...
...
@@ -4,10 +4,13 @@
*/
#include <linux/bitops.h>
#include <linux/gpio/consumer.h>
#include <linux/i2c.h>
#include <linux/interrupt.h>
#include <linux/ioport.h>
#include <linux/irq.h>
#include <linux/irqdomain.h>
#include <linux/mfd/core.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_platform.h>
...
...
@@ -15,8 +18,6 @@
#include <linux/regmap.h>
#include <linux/slab.h>
#include <dt-bindings/mfd/qcom-pm8008.h>
#define I2C_INTR_STATUS_BASE 0x0550
#define INT_RT_STS_OFFSET 0x10
#define INT_SET_TYPE_OFFSET 0x11
...
...
@@ -37,34 +38,54 @@ enum {
#define PM8008_PERIPH_0_BASE 0x900
#define PM8008_PERIPH_1_BASE 0x2400
#define PM8008_PERIPH_2_BASE 0x
C
000
#define PM8008_PERIPH_3_BASE 0x
C
100
#define PM8008_PERIPH_2_BASE 0x
c
000
#define PM8008_PERIPH_3_BASE 0x
c
100
#define PM8008_TEMP_ALARM_ADDR PM8008_PERIPH_1_BASE
#define PM8008_GPIO1_ADDR PM8008_PERIPH_2_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
{
SET_TYPE_INDEX
,
POLARITY_HI_INDEX
,
POLARITY_LO_INDEX
,
};
static
unsigned
int
pm8008_config_regs
[]
=
{
static
const
unsigned
int
pm8008_config_regs
[]
=
{
INT_SET_TYPE_OFFSET
,
INT_POL_HIGH_OFFSET
,
INT_POL_LOW_OFFSET
,
};
static
struct
regmap_irq
pm8008_irqs
[]
=
{
REGMAP_IRQ_REG
(
PM8008_IRQ_MISC_UVLO
,
PM8008_MISC
,
BIT
(
0
)),
REGMAP_IRQ_REG
(
PM8008_IRQ_MISC_OVLO
,
PM8008_MISC
,
BIT
(
1
)),
REGMAP_IRQ_REG
(
PM8008_IRQ_MISC_OTST2
,
PM8008_MISC
,
BIT
(
2
)),
REGMAP_IRQ_REG
(
PM8008_IRQ_MISC_OTST3
,
PM8008_MISC
,
BIT
(
3
)),
REGMAP_IRQ_REG
(
PM8008_IRQ_MISC_LDO_OCP
,
PM8008_MISC
,
BIT
(
4
)),
REGMAP_IRQ_REG
(
PM8008_IRQ_TEMP_ALARM
,
PM8008_TEMP_ALARM
,
BIT
(
0
)),
REGMAP_IRQ_REG
(
PM8008_IRQ_GPIO1
,
PM8008_GPIO1
,
BIT
(
0
)),
REGMAP_IRQ_REG
(
PM8008_IRQ_GPIO2
,
PM8008_GPIO2
,
BIT
(
0
)),
#define _IRQ(_irq, _off, _mask, _types) \
[_irq] = { \
.reg_offset = (_off), \
.mask = (_mask), \
.type = { \
.type_reg_offset = (_off), \
.types_supported = (_types), \
}, \
}
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
[]
=
{
...
...
@@ -118,8 +139,8 @@ static int pm8008_set_type_config(unsigned int **buf, unsigned int type,
return
0
;
}
static
struct
regmap_irq_chip
pm8008_irq_chip
=
{
.
name
=
"pm8008
_irq
"
,
static
const
struct
regmap_irq_chip
pm8008_irq_chip
=
{
.
name
=
"pm8008"
,
.
main_status
=
I2C_INTR_STATUS_BASE
,
.
num_main_regs
=
1
,
.
irqs
=
pm8008_irqs
,
...
...
@@ -137,62 +158,106 @@ static struct regmap_irq_chip pm8008_irq_chip = {
.
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
,
.
val_bits
=
8
,
.
max_register
=
0x
FFFF
,
.
max_register
=
0x
ffff
,
};
static
int
pm8008_probe_irq_peripherals
(
struct
device
*
dev
,
struct
regmap
*
regmap
,
int
client_irq
)
{
int
rc
,
i
;
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
;
static
const
struct
regmap_config
pm8008_regmap_cfg_2
=
{
.
name
=
"secondary"
,
.
reg_bits
=
16
,
.
val_bits
=
8
,
.
max_register
=
0xffff
,
};
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
)
type
->
types_supported
=
IRQ_TYPE_EDGE_RISING
;
else
type
->
types_supported
=
(
IRQ_TYPE_EDGE_BOTH
|
IRQ_TYPE_LEVEL_HIGH
|
IRQ_TYPE_LEVEL_LOW
);
}
static
const
struct
mfd_cell
pm8008_cells
[]
=
{
MFD_CELL_NAME
(
"pm8008-regulator"
),
MFD_CELL_RES
(
"qpnp-temp-alarm"
,
pm8008_temp_res
),
MFD_CELL_NAME
(
"pm8008-gpio"
),
};
rc
=
devm_regmap_add_irq_chip
(
dev
,
regmap
,
client_irq
,
IRQF_SHARED
,
0
,
&
pm8008_irq_chip
,
&
irq_data
);
if
(
rc
)
{
dev_err
(
dev
,
"Failed to add IRQ chip: %d
\n
"
,
rc
);
return
rc
;
}
static
void
devm_irq_domain_fwnode_release
(
void
*
data
)
{
struct
fwnode_handle
*
fwnode
=
data
;
return
0
;
irq_domain_free_fwnode
(
fwnode
)
;
}
static
int
pm8008_probe
(
struct
i2c_client
*
client
)
{
int
rc
;
struct
device
*
dev
;
struct
regmap
*
regmap
;
struct
regmap_irq_chip_data
*
irq_data
;
struct
device
*
dev
=
&
client
->
dev
;
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
);
ret
=
regmap_attach_dev
(
dev
,
regmap2
,
&
pm8008_regmap_cfg_2
);
if
(
ret
)
return
ret
;
dev
=
&
client
->
dev
;
/* Default regmap must be attached last. */
regmap
=
devm_regmap_init_i2c
(
client
,
&
qcom_mfd_regmap_cfg
);
if
(
IS_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
);
if
(
rc
)
dev_err
(
dev
,
"Failed to probe irq periphs: %d
\n
"
,
rc
);
/*
* The PMIC does not appear to require a post-reset delay, but wait
* for a millisecond for now anyway.
*/
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
[]
=
{
...
...
drivers/regulator/Kconfig
View file @
04f38933
...
...
@@ -1033,6 +1033,13 @@ config REGULATOR_PWM
This driver supports PWM controlled voltage regulators. PWM
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
tristate "Qualcomm REFGEN regulator driver"
depends on ARCH_QCOM || COMPILE_TEST
...
...
drivers/regulator/Makefile
View file @
04f38933
...
...
@@ -113,6 +113,7 @@ obj-$(CONFIG_REGULATOR_MT6380) += mt6380-regulator.o
obj-$(CONFIG_REGULATOR_MT6397)
+=
mt6397-regulator.o
obj-$(CONFIG_REGULATOR_MTK_DVFSRC)
+=
mtk-dvfsrc-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_RPM)
+=
qcom_rpm-regulator.o
obj-$(CONFIG_REGULATOR_QCOM_RPMH)
+=
qcom-rpmh-regulator.o
...
...
drivers/regulator/qcom-pm8008-regulator.c
0 → 100644
View file @
04f38933
// 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"
);
include/dt-bindings/mfd/qcom-pm8008.h
deleted
100644 → 0
View file @
5ffe70d8
/* 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
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment