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
4136e455
Commit
4136e455
authored
Jan 24, 2019
by
Linus Walleij
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'ib-qcom-spmi' into devel
parents
b0c3e54e
e7dc6af8
Changes
11
Hide whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
225 additions
and
156 deletions
+225
-156
Documentation/devicetree/bindings/pinctrl/qcom,pmic-gpio.txt
Documentation/devicetree/bindings/pinctrl/qcom,pmic-gpio.txt
+1
-0
arch/arm/boot/dts/qcom-pm8941.dtsi
arch/arm/boot/dts/qcom-pm8941.dtsi
+2
-36
arch/arm/boot/dts/qcom-pma8084.dtsi
arch/arm/boot/dts/qcom-pma8084.dtsi
+2
-22
arch/arm64/boot/dts/qcom/pm8005.dtsi
arch/arm64/boot/dts/qcom/pm8005.dtsi
+2
-4
arch/arm64/boot/dts/qcom/pm8998.dtsi
arch/arm64/boot/dts/qcom/pm8998.dtsi
+2
-26
arch/arm64/boot/dts/qcom/pmi8994.dtsi
arch/arm64/boot/dts/qcom/pmi8994.dtsi
+2
-10
arch/arm64/boot/dts/qcom/pmi8998.dtsi
arch/arm64/boot/dts/qcom/pmi8998.dtsi
+2
-14
drivers/gpio/gpiolib.c
drivers/gpio/gpiolib.c
+37
-0
drivers/pinctrl/qcom/pinctrl-spmi-gpio.c
drivers/pinctrl/qcom/pinctrl-spmi-gpio.c
+116
-24
drivers/spmi/spmi-pmic-arb.c
drivers/spmi/spmi-pmic-arb.c
+54
-20
include/linux/gpio/driver.h
include/linux/gpio/driver.h
+5
-0
No files found.
Documentation/devicetree/bindings/pinctrl/qcom,pmic-gpio.txt
View file @
4136e455
...
@@ -19,6 +19,7 @@ PMIC's from Qualcomm.
...
@@ -19,6 +19,7 @@ PMIC's from Qualcomm.
"qcom,pm8998-gpio"
"qcom,pm8998-gpio"
"qcom,pma8084-gpio"
"qcom,pma8084-gpio"
"qcom,pmi8994-gpio"
"qcom,pmi8994-gpio"
"qcom,pmi8998-gpio"
"qcom,pms405-gpio"
"qcom,pms405-gpio"
And must contain either "qcom,spmi-gpio" or "qcom,ssbi-gpio"
And must contain either "qcom,spmi-gpio" or "qcom,ssbi-gpio"
...
...
arch/arm/boot/dts/qcom-pm8941.dtsi
View file @
4136e455
...
@@ -64,42 +64,8 @@ pm8941_gpios: gpios@c000 {
...
@@ -64,42 +64,8 @@ pm8941_gpios: gpios@c000 {
reg = <0xc000>;
reg = <0xc000>;
gpio-controller;
gpio-controller;
#gpio-cells = <2>;
#gpio-cells = <2>;
interrupts = <0 0xc0 0 IRQ_TYPE_NONE>,
interrupt-controller;
<0 0xc1 0 IRQ_TYPE_NONE>,
#interrupt-cells = <2>;
<0 0xc2 0 IRQ_TYPE_NONE>,
<0 0xc3 0 IRQ_TYPE_NONE>,
<0 0xc4 0 IRQ_TYPE_NONE>,
<0 0xc5 0 IRQ_TYPE_NONE>,
<0 0xc6 0 IRQ_TYPE_NONE>,
<0 0xc7 0 IRQ_TYPE_NONE>,
<0 0xc8 0 IRQ_TYPE_NONE>,
<0 0xc9 0 IRQ_TYPE_NONE>,
<0 0xca 0 IRQ_TYPE_NONE>,
<0 0xcb 0 IRQ_TYPE_NONE>,
<0 0xcc 0 IRQ_TYPE_NONE>,
<0 0xcd 0 IRQ_TYPE_NONE>,
<0 0xce 0 IRQ_TYPE_NONE>,
<0 0xcf 0 IRQ_TYPE_NONE>,
<0 0xd0 0 IRQ_TYPE_NONE>,
<0 0xd1 0 IRQ_TYPE_NONE>,
<0 0xd2 0 IRQ_TYPE_NONE>,
<0 0xd3 0 IRQ_TYPE_NONE>,
<0 0xd4 0 IRQ_TYPE_NONE>,
<0 0xd5 0 IRQ_TYPE_NONE>,
<0 0xd6 0 IRQ_TYPE_NONE>,
<0 0xd7 0 IRQ_TYPE_NONE>,
<0 0xd8 0 IRQ_TYPE_NONE>,
<0 0xd9 0 IRQ_TYPE_NONE>,
<0 0xda 0 IRQ_TYPE_NONE>,
<0 0xdb 0 IRQ_TYPE_NONE>,
<0 0xdc 0 IRQ_TYPE_NONE>,
<0 0xdd 0 IRQ_TYPE_NONE>,
<0 0xde 0 IRQ_TYPE_NONE>,
<0 0xdf 0 IRQ_TYPE_NONE>,
<0 0xe0 0 IRQ_TYPE_NONE>,
<0 0xe1 0 IRQ_TYPE_NONE>,
<0 0xe2 0 IRQ_TYPE_NONE>,
<0 0xe3 0 IRQ_TYPE_NONE>;
boost_bypass_n_pin: boost-bypass {
boost_bypass_n_pin: boost-bypass {
pins = "gpio21";
pins = "gpio21";
...
...
arch/arm/boot/dts/qcom-pma8084.dtsi
View file @
4136e455
...
@@ -32,28 +32,8 @@ pma8084_gpios: gpios@c000 {
...
@@ -32,28 +32,8 @@ pma8084_gpios: gpios@c000 {
reg = <0xc000>;
reg = <0xc000>;
gpio-controller;
gpio-controller;
#gpio-cells = <2>;
#gpio-cells = <2>;
interrupts = <0 0xc0 0 IRQ_TYPE_NONE>,
interrupt-controller;
<0 0xc1 0 IRQ_TYPE_NONE>,
#interrupt-cells = <2>;
<0 0xc2 0 IRQ_TYPE_NONE>,
<0 0xc3 0 IRQ_TYPE_NONE>,
<0 0xc4 0 IRQ_TYPE_NONE>,
<0 0xc5 0 IRQ_TYPE_NONE>,
<0 0xc6 0 IRQ_TYPE_NONE>,
<0 0xc7 0 IRQ_TYPE_NONE>,
<0 0xc8 0 IRQ_TYPE_NONE>,
<0 0xc9 0 IRQ_TYPE_NONE>,
<0 0xca 0 IRQ_TYPE_NONE>,
<0 0xcb 0 IRQ_TYPE_NONE>,
<0 0xcc 0 IRQ_TYPE_NONE>,
<0 0xcd 0 IRQ_TYPE_NONE>,
<0 0xce 0 IRQ_TYPE_NONE>,
<0 0xcf 0 IRQ_TYPE_NONE>,
<0 0xd0 0 IRQ_TYPE_NONE>,
<0 0xd1 0 IRQ_TYPE_NONE>,
<0 0xd2 0 IRQ_TYPE_NONE>,
<0 0xd3 0 IRQ_TYPE_NONE>,
<0 0xd4 0 IRQ_TYPE_NONE>,
<0 0xd5 0 IRQ_TYPE_NONE>;
};
};
pma8084_mpps: mpps@a000 {
pma8084_mpps: mpps@a000 {
...
...
arch/arm64/boot/dts/qcom/pm8005.dtsi
View file @
4136e455
...
@@ -16,10 +16,8 @@ pm8005_gpio: gpios@c000 {
...
@@ -16,10 +16,8 @@ pm8005_gpio: gpios@c000 {
reg = <0xc000>;
reg = <0xc000>;
gpio-controller;
gpio-controller;
#gpio-cells = <2>;
#gpio-cells = <2>;
interrupts = <0 0xc0 0 IRQ_TYPE_NONE>,
interrupt-controller;
<0 0xc1 0 IRQ_TYPE_NONE>,
#interrupt-cells = <2>;
<0 0xc2 0 IRQ_TYPE_NONE>,
<0 0xc3 0 IRQ_TYPE_NONE>;
};
};
};
};
...
...
arch/arm64/boot/dts/qcom/pm8998.dtsi
View file @
4136e455
...
@@ -94,32 +94,8 @@ pm8998_gpio: gpios@c000 {
...
@@ -94,32 +94,8 @@ pm8998_gpio: gpios@c000 {
reg = <0xc000>;
reg = <0xc000>;
gpio-controller;
gpio-controller;
#gpio-cells = <2>;
#gpio-cells = <2>;
interrupts = <0 0xc0 0 IRQ_TYPE_NONE>,
interrupt-controller;
<0 0xc1 0 IRQ_TYPE_NONE>,
#interrupt-cells = <2>;
<0 0xc2 0 IRQ_TYPE_NONE>,
<0 0xc3 0 IRQ_TYPE_NONE>,
<0 0xc4 0 IRQ_TYPE_NONE>,
<0 0xc5 0 IRQ_TYPE_NONE>,
<0 0xc6 0 IRQ_TYPE_NONE>,
<0 0xc7 0 IRQ_TYPE_NONE>,
<0 0xc8 0 IRQ_TYPE_NONE>,
<0 0xc9 0 IRQ_TYPE_NONE>,
<0 0xca 0 IRQ_TYPE_NONE>,
<0 0xcb 0 IRQ_TYPE_NONE>,
<0 0xcc 0 IRQ_TYPE_NONE>,
<0 0xcd 0 IRQ_TYPE_NONE>,
<0 0xce 0 IRQ_TYPE_NONE>,
<0 0xcf 0 IRQ_TYPE_NONE>,
<0 0xd0 0 IRQ_TYPE_NONE>,
<0 0xd1 0 IRQ_TYPE_NONE>,
<0 0xd2 0 IRQ_TYPE_NONE>,
<0 0xd3 0 IRQ_TYPE_NONE>,
<0 0xd4 0 IRQ_TYPE_NONE>,
<0 0xd5 0 IRQ_TYPE_NONE>,
<0 0xd6 0 IRQ_TYPE_NONE>,
<0 0xd7 0 IRQ_TYPE_NONE>,
<0 0xd8 0 IRQ_TYPE_NONE>,
<0 0xd9 0 IRQ_TYPE_NONE>;
};
};
};
};
...
...
arch/arm64/boot/dts/qcom/pmi8994.dtsi
View file @
4136e455
...
@@ -15,16 +15,8 @@ pmi8994_gpios: gpios@c000 {
...
@@ -15,16 +15,8 @@ pmi8994_gpios: gpios@c000 {
reg = <0xc000>;
reg = <0xc000>;
gpio-controller;
gpio-controller;
#gpio-cells = <2>;
#gpio-cells = <2>;
interrupts = <2 0xc0 0 IRQ_TYPE_NONE>,
interrupt-controller;
<2 0xc1 0 IRQ_TYPE_NONE>,
#interrupt-cells = <2>;
<2 0xc2 0 IRQ_TYPE_NONE>,
<2 0xc3 0 IRQ_TYPE_NONE>,
<2 0xc4 0 IRQ_TYPE_NONE>,
<2 0xc5 0 IRQ_TYPE_NONE>,
<2 0xc6 0 IRQ_TYPE_NONE>,
<2 0xc7 0 IRQ_TYPE_NONE>,
<2 0xc8 0 IRQ_TYPE_NONE>,
<2 0xc9 0 IRQ_TYPE_NONE>;
};
};
};
};
...
...
arch/arm64/boot/dts/qcom/pmi8998.dtsi
View file @
4136e455
...
@@ -14,20 +14,8 @@ pmi8998_gpio: gpios@c000 {
...
@@ -14,20 +14,8 @@ pmi8998_gpio: gpios@c000 {
reg = <0xc000>;
reg = <0xc000>;
gpio-controller;
gpio-controller;
#gpio-cells = <2>;
#gpio-cells = <2>;
interrupts = <0 0xc0 0 IRQ_TYPE_NONE>,
interrupt-controller;
<0 0xc1 0 IRQ_TYPE_NONE>,
#interrupt-cells = <2>;
<0 0xc2 0 IRQ_TYPE_NONE>,
<0 0xc3 0 IRQ_TYPE_NONE>,
<0 0xc4 0 IRQ_TYPE_NONE>,
<0 0xc5 0 IRQ_TYPE_NONE>,
<0 0xc6 0 IRQ_TYPE_NONE>,
<0 0xc7 0 IRQ_TYPE_NONE>,
<0 0xc8 0 IRQ_TYPE_NONE>,
<0 0xc9 0 IRQ_TYPE_NONE>,
<0 0xca 0 IRQ_TYPE_NONE>,
<0 0xcb 0 IRQ_TYPE_NONE>,
<0 0xcc 0 IRQ_TYPE_NONE>,
<0 0xcd 0 IRQ_TYPE_NONE>;
};
};
};
};
...
...
drivers/gpio/gpiolib.c
View file @
4136e455
...
@@ -1775,6 +1775,43 @@ static const struct irq_domain_ops gpiochip_domain_ops = {
...
@@ -1775,6 +1775,43 @@ static const struct irq_domain_ops gpiochip_domain_ops = {
.
xlate
=
irq_domain_xlate_twocell
,
.
xlate
=
irq_domain_xlate_twocell
,
};
};
/**
* gpiochip_irq_domain_activate() - Lock a GPIO to be used as an IRQ
* @domain: The IRQ domain used by this IRQ chip
* @data: Outermost irq_data associated with the IRQ
* @reserve: If set, only reserve an interrupt vector instead of assigning one
*
* This function is a wrapper that calls gpiochip_lock_as_irq() and is to be
* used as the activate function for the &struct irq_domain_ops. The host_data
* for the IRQ domain must be the &struct gpio_chip.
*/
int
gpiochip_irq_domain_activate
(
struct
irq_domain
*
domain
,
struct
irq_data
*
data
,
bool
reserve
)
{
struct
gpio_chip
*
chip
=
domain
->
host_data
;
return
gpiochip_lock_as_irq
(
chip
,
data
->
hwirq
);
}
EXPORT_SYMBOL_GPL
(
gpiochip_irq_domain_activate
);
/**
* gpiochip_irq_domain_deactivate() - Unlock a GPIO used as an IRQ
* @domain: The IRQ domain used by this IRQ chip
* @data: Outermost irq_data associated with the IRQ
*
* This function is a wrapper that will call gpiochip_unlock_as_irq() and is to
* be used as the deactivate function for the &struct irq_domain_ops. The
* host_data for the IRQ domain must be the &struct gpio_chip.
*/
void
gpiochip_irq_domain_deactivate
(
struct
irq_domain
*
domain
,
struct
irq_data
*
data
)
{
struct
gpio_chip
*
chip
=
domain
->
host_data
;
return
gpiochip_unlock_as_irq
(
chip
,
data
->
hwirq
);
}
EXPORT_SYMBOL_GPL
(
gpiochip_irq_domain_deactivate
);
static
int
gpiochip_to_irq
(
struct
gpio_chip
*
chip
,
unsigned
offset
)
static
int
gpiochip_to_irq
(
struct
gpio_chip
*
chip
,
unsigned
offset
)
{
{
if
(
!
gpiochip_irqchip_irq_valid
(
chip
,
offset
))
if
(
!
gpiochip_irqchip_irq_valid
(
chip
,
offset
))
...
...
drivers/pinctrl/qcom/pinctrl-spmi-gpio.c
View file @
4136e455
...
@@ -12,6 +12,7 @@
...
@@ -12,6 +12,7 @@
*/
*/
#include <linux/gpio/driver.h>
#include <linux/gpio/driver.h>
#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of.h>
#include <linux/of_irq.h>
#include <linux/of_irq.h>
...
@@ -136,7 +137,6 @@ enum pmic_gpio_func_index {
...
@@ -136,7 +137,6 @@ enum pmic_gpio_func_index {
/**
/**
* struct pmic_gpio_pad - keep current GPIO settings
* struct pmic_gpio_pad - keep current GPIO settings
* @base: Address base in SPMI device.
* @base: Address base in SPMI device.
* @irq: IRQ number which this GPIO generate.
* @is_enabled: Set to false when GPIO should be put in high Z state.
* @is_enabled: Set to false when GPIO should be put in high Z state.
* @out_value: Cached pin output value
* @out_value: Cached pin output value
* @have_buffer: Set to true if GPIO output could be configured in push-pull,
* @have_buffer: Set to true if GPIO output could be configured in push-pull,
...
@@ -156,7 +156,6 @@ enum pmic_gpio_func_index {
...
@@ -156,7 +156,6 @@ enum pmic_gpio_func_index {
*/
*/
struct
pmic_gpio_pad
{
struct
pmic_gpio_pad
{
u16
base
;
u16
base
;
int
irq
;
bool
is_enabled
;
bool
is_enabled
;
bool
out_value
;
bool
out_value
;
bool
have_buffer
;
bool
have_buffer
;
...
@@ -179,6 +178,8 @@ struct pmic_gpio_state {
...
@@ -179,6 +178,8 @@ struct pmic_gpio_state {
struct
regmap
*
map
;
struct
regmap
*
map
;
struct
pinctrl_dev
*
ctrl
;
struct
pinctrl_dev
*
ctrl
;
struct
gpio_chip
chip
;
struct
gpio_chip
chip
;
struct
fwnode_handle
*
fwnode
;
struct
irq_domain
*
domain
;
};
};
static
const
struct
pinconf_generic_params
pmic_gpio_bindings
[]
=
{
static
const
struct
pinconf_generic_params
pmic_gpio_bindings
[]
=
{
...
@@ -761,11 +762,18 @@ static int pmic_gpio_of_xlate(struct gpio_chip *chip,
...
@@ -761,11 +762,18 @@ static int pmic_gpio_of_xlate(struct gpio_chip *chip,
static
int
pmic_gpio_to_irq
(
struct
gpio_chip
*
chip
,
unsigned
pin
)
static
int
pmic_gpio_to_irq
(
struct
gpio_chip
*
chip
,
unsigned
pin
)
{
{
struct
pmic_gpio_state
*
state
=
gpiochip_get_data
(
chip
);
struct
pmic_gpio_state
*
state
=
gpiochip_get_data
(
chip
);
struct
pmic_gpio_pad
*
pad
;
struct
irq_fwspec
fwspec
;
pad
=
state
->
ctrl
->
desc
->
pins
[
pin
].
drv_data
;
fwspec
.
fwnode
=
state
->
fwnode
;
fwspec
.
param_count
=
2
;
fwspec
.
param
[
0
]
=
pin
+
PMIC_GPIO_PHYSICAL_OFFSET
;
/*
* Set the type to a safe value temporarily. This will be overwritten
* later with the proper value by irq_set_type.
*/
fwspec
.
param
[
1
]
=
IRQ_TYPE_EDGE_RISING
;
return
pad
->
irq
;
return
irq_create_fwspec_mapping
(
&
fwspec
)
;
}
}
static
void
pmic_gpio_dbg_show
(
struct
seq_file
*
s
,
struct
gpio_chip
*
chip
)
static
void
pmic_gpio_dbg_show
(
struct
seq_file
*
s
,
struct
gpio_chip
*
chip
)
...
@@ -935,8 +943,78 @@ static int pmic_gpio_populate(struct pmic_gpio_state *state,
...
@@ -935,8 +943,78 @@ static int pmic_gpio_populate(struct pmic_gpio_state *state,
return
0
;
return
0
;
}
}
static
struct
irq_chip
pmic_gpio_irq_chip
=
{
.
name
=
"spmi-gpio"
,
.
irq_ack
=
irq_chip_ack_parent
,
.
irq_mask
=
irq_chip_mask_parent
,
.
irq_unmask
=
irq_chip_unmask_parent
,
.
irq_set_type
=
irq_chip_set_type_parent
,
.
irq_set_wake
=
irq_chip_set_wake_parent
,
.
flags
=
IRQCHIP_MASK_ON_SUSPEND
,
};
static
int
pmic_gpio_domain_translate
(
struct
irq_domain
*
domain
,
struct
irq_fwspec
*
fwspec
,
unsigned
long
*
hwirq
,
unsigned
int
*
type
)
{
struct
pmic_gpio_state
*
state
=
container_of
(
domain
->
host_data
,
struct
pmic_gpio_state
,
chip
);
if
(
fwspec
->
param_count
!=
2
||
fwspec
->
param
[
0
]
>=
state
->
chip
.
ngpio
)
return
-
EINVAL
;
*
hwirq
=
fwspec
->
param
[
0
]
-
PMIC_GPIO_PHYSICAL_OFFSET
;
*
type
=
fwspec
->
param
[
1
];
return
0
;
}
static
int
pmic_gpio_domain_alloc
(
struct
irq_domain
*
domain
,
unsigned
int
virq
,
unsigned
int
nr_irqs
,
void
*
data
)
{
struct
pmic_gpio_state
*
state
=
container_of
(
domain
->
host_data
,
struct
pmic_gpio_state
,
chip
);
struct
irq_fwspec
*
fwspec
=
data
;
struct
irq_fwspec
parent_fwspec
;
irq_hw_number_t
hwirq
;
unsigned
int
type
;
int
ret
,
i
;
ret
=
pmic_gpio_domain_translate
(
domain
,
fwspec
,
&
hwirq
,
&
type
);
if
(
ret
)
return
ret
;
for
(
i
=
0
;
i
<
nr_irqs
;
i
++
)
irq_domain_set_info
(
domain
,
virq
+
i
,
hwirq
+
i
,
&
pmic_gpio_irq_chip
,
state
,
handle_level_irq
,
NULL
,
NULL
);
parent_fwspec
.
fwnode
=
domain
->
parent
->
fwnode
;
parent_fwspec
.
param_count
=
4
;
parent_fwspec
.
param
[
0
]
=
0
;
parent_fwspec
.
param
[
1
]
=
hwirq
+
0xc0
;
parent_fwspec
.
param
[
2
]
=
0
;
parent_fwspec
.
param
[
3
]
=
fwspec
->
param
[
1
];
return
irq_domain_alloc_irqs_parent
(
domain
,
virq
,
nr_irqs
,
&
parent_fwspec
);
}
static
const
struct
irq_domain_ops
pmic_gpio_domain_ops
=
{
.
activate
=
gpiochip_irq_domain_activate
,
.
alloc
=
pmic_gpio_domain_alloc
,
.
deactivate
=
gpiochip_irq_domain_deactivate
,
.
free
=
irq_domain_free_irqs_common
,
.
translate
=
pmic_gpio_domain_translate
,
};
static
int
pmic_gpio_probe
(
struct
platform_device
*
pdev
)
static
int
pmic_gpio_probe
(
struct
platform_device
*
pdev
)
{
{
struct
irq_domain
*
parent_domain
;
struct
device_node
*
parent_node
;
struct
device
*
dev
=
&
pdev
->
dev
;
struct
device
*
dev
=
&
pdev
->
dev
;
struct
pinctrl_pin_desc
*
pindesc
;
struct
pinctrl_pin_desc
*
pindesc
;
struct
pinctrl_desc
*
pctrldesc
;
struct
pinctrl_desc
*
pctrldesc
;
...
@@ -951,13 +1029,7 @@ static int pmic_gpio_probe(struct platform_device *pdev)
...
@@ -951,13 +1029,7 @@ static int pmic_gpio_probe(struct platform_device *pdev)
return
ret
;
return
ret
;
}
}
npins
=
platform_irq_count
(
pdev
);
npins
=
(
uintptr_t
)
device_get_match_data
(
&
pdev
->
dev
);
if
(
!
npins
)
return
-
EINVAL
;
if
(
npins
<
0
)
return
npins
;
BUG_ON
(
npins
>
ARRAY_SIZE
(
pmic_gpio_groups
));
state
=
devm_kzalloc
(
dev
,
sizeof
(
*
state
),
GFP_KERNEL
);
state
=
devm_kzalloc
(
dev
,
sizeof
(
*
state
),
GFP_KERNEL
);
if
(
!
state
)
if
(
!
state
)
...
@@ -999,10 +1071,6 @@ static int pmic_gpio_probe(struct platform_device *pdev)
...
@@ -999,10 +1071,6 @@ static int pmic_gpio_probe(struct platform_device *pdev)
pindesc
->
number
=
i
;
pindesc
->
number
=
i
;
pindesc
->
name
=
pmic_gpio_groups
[
i
];
pindesc
->
name
=
pmic_gpio_groups
[
i
];
pad
->
irq
=
platform_get_irq
(
pdev
,
i
);
if
(
pad
->
irq
<
0
)
return
pad
->
irq
;
pad
->
base
=
reg
+
i
*
PMIC_GPIO_ADDRESS_RANGE
;
pad
->
base
=
reg
+
i
*
PMIC_GPIO_ADDRESS_RANGE
;
ret
=
pmic_gpio_populate
(
state
,
pad
);
ret
=
pmic_gpio_populate
(
state
,
pad
);
...
@@ -1022,10 +1090,28 @@ static int pmic_gpio_probe(struct platform_device *pdev)
...
@@ -1022,10 +1090,28 @@ static int pmic_gpio_probe(struct platform_device *pdev)
if
(
IS_ERR
(
state
->
ctrl
))
if
(
IS_ERR
(
state
->
ctrl
))
return
PTR_ERR
(
state
->
ctrl
);
return
PTR_ERR
(
state
->
ctrl
);
parent_node
=
of_irq_find_parent
(
state
->
dev
->
of_node
);
if
(
!
parent_node
)
return
-
ENXIO
;
parent_domain
=
irq_find_host
(
parent_node
);
of_node_put
(
parent_node
);
if
(
!
parent_domain
)
return
-
ENXIO
;
state
->
fwnode
=
of_node_to_fwnode
(
state
->
dev
->
of_node
);
state
->
domain
=
irq_domain_create_hierarchy
(
parent_domain
,
0
,
state
->
chip
.
ngpio
,
state
->
fwnode
,
&
pmic_gpio_domain_ops
,
&
state
->
chip
);
if
(
!
state
->
domain
)
return
-
ENODEV
;
ret
=
gpiochip_add_data
(
&
state
->
chip
,
state
);
ret
=
gpiochip_add_data
(
&
state
->
chip
,
state
);
if
(
ret
)
{
if
(
ret
)
{
dev_err
(
state
->
dev
,
"can't add gpio chip
\n
"
);
dev_err
(
state
->
dev
,
"can't add gpio chip
\n
"
);
return
ret
;
goto
err_chip_add_data
;
}
}
/*
/*
...
@@ -1051,6 +1137,8 @@ static int pmic_gpio_probe(struct platform_device *pdev)
...
@@ -1051,6 +1137,8 @@ static int pmic_gpio_probe(struct platform_device *pdev)
err_range:
err_range:
gpiochip_remove
(
&
state
->
chip
);
gpiochip_remove
(
&
state
->
chip
);
err_chip_add_data:
irq_domain_remove
(
state
->
domain
);
return
ret
;
return
ret
;
}
}
...
@@ -1059,17 +1147,21 @@ static int pmic_gpio_remove(struct platform_device *pdev)
...
@@ -1059,17 +1147,21 @@ static int pmic_gpio_remove(struct platform_device *pdev)
struct
pmic_gpio_state
*
state
=
platform_get_drvdata
(
pdev
);
struct
pmic_gpio_state
*
state
=
platform_get_drvdata
(
pdev
);
gpiochip_remove
(
&
state
->
chip
);
gpiochip_remove
(
&
state
->
chip
);
irq_domain_remove
(
state
->
domain
);
return
0
;
return
0
;
}
}
static
const
struct
of_device_id
pmic_gpio_of_match
[]
=
{
static
const
struct
of_device_id
pmic_gpio_of_match
[]
=
{
{
.
compatible
=
"qcom,pm8916-gpio"
},
/* 4 GPIO's */
{
.
compatible
=
"qcom,pm8005-gpio"
,
.
data
=
(
void
*
)
4
},
{
.
compatible
=
"qcom,pm8941-gpio"
},
/* 36 GPIO's */
{
.
compatible
=
"qcom,pm8916-gpio"
,
.
data
=
(
void
*
)
4
},
{
.
compatible
=
"qcom,pm8994-gpio"
},
/* 22 GPIO's */
{
.
compatible
=
"qcom,pm8941-gpio"
,
.
data
=
(
void
*
)
36
},
{
.
compatible
=
"qcom,pmi8994-gpio"
},
/* 10 GPIO's */
{
.
compatible
=
"qcom,pm8994-gpio"
,
.
data
=
(
void
*
)
22
},
{
.
compatible
=
"qcom,pma8084-gpio"
},
/* 22 GPIO's */
{
.
compatible
=
"qcom,pmi8994-gpio"
,
.
data
=
(
void
*
)
10
},
{
.
compatible
=
"qcom,pms405-gpio"
},
/* 12 GPIO's, holes on 1 9 10 */
{
.
compatible
=
"qcom,pm8998-gpio"
,
.
data
=
(
void
*
)
26
},
{
.
compatible
=
"qcom,spmi-gpio"
},
/* Generic */
{
.
compatible
=
"qcom,pmi8998-gpio"
,
.
data
=
(
void
*
)
14
},
{
.
compatible
=
"qcom,pma8084-gpio"
,
.
data
=
(
void
*
)
22
},
/* pms405 has 12 GPIOs with holes on 1, 9, and 10 */
{
.
compatible
=
"qcom,pms405-gpio"
,
.
data
=
(
void
*
)
12
},
{
},
{
},
};
};
...
...
drivers/spmi/spmi-pmic-arb.c
View file @
4136e455
...
@@ -666,7 +666,8 @@ static int qpnpint_get_irqchip_state(struct irq_data *d,
...
@@ -666,7 +666,8 @@ static int qpnpint_get_irqchip_state(struct irq_data *d,
return
0
;
return
0
;
}
}
static
int
qpnpint_irq_request_resources
(
struct
irq_data
*
d
)
static
int
qpnpint_irq_domain_activate
(
struct
irq_domain
*
domain
,
struct
irq_data
*
d
,
bool
reserve
)
{
{
struct
spmi_pmic_arb
*
pmic_arb
=
irq_data_get_irq_chip_data
(
d
);
struct
spmi_pmic_arb
*
pmic_arb
=
irq_data_get_irq_chip_data
(
d
);
u16
periph
=
hwirq_to_per
(
d
->
hwirq
);
u16
periph
=
hwirq_to_per
(
d
->
hwirq
);
...
@@ -692,27 +693,25 @@ static struct irq_chip pmic_arb_irqchip = {
...
@@ -692,27 +693,25 @@ static struct irq_chip pmic_arb_irqchip = {
.
irq_set_type
=
qpnpint_irq_set_type
,
.
irq_set_type
=
qpnpint_irq_set_type
,
.
irq_set_wake
=
qpnpint_irq_set_wake
,
.
irq_set_wake
=
qpnpint_irq_set_wake
,
.
irq_get_irqchip_state
=
qpnpint_get_irqchip_state
,
.
irq_get_irqchip_state
=
qpnpint_get_irqchip_state
,
.
irq_request_resources
=
qpnpint_irq_request_resources
,
.
flags
=
IRQCHIP_MASK_ON_SUSPEND
,
.
flags
=
IRQCHIP_MASK_ON_SUSPEND
,
};
};
static
int
qpnpint_irq_domain_dt_translate
(
struct
irq_domain
*
d
,
static
int
qpnpint_irq_domain_translate
(
struct
irq_domain
*
d
,
struct
device_node
*
controller
,
struct
irq_fwspec
*
fwspec
,
const
u32
*
intspec
,
unsigned
long
*
out_hwirq
,
unsigned
int
intsize
,
unsigned
int
*
out_type
)
unsigned
long
*
out_hwirq
,
unsigned
int
*
out_type
)
{
{
struct
spmi_pmic_arb
*
pmic_arb
=
d
->
host_data
;
struct
spmi_pmic_arb
*
pmic_arb
=
d
->
host_data
;
u32
*
intspec
=
fwspec
->
param
;
u16
apid
,
ppid
;
u16
apid
,
ppid
;
int
rc
;
int
rc
;
dev_dbg
(
&
pmic_arb
->
spmic
->
dev
,
"intspec[0] 0x%1x intspec[1] 0x%02x intspec[2] 0x%02x
\n
"
,
dev_dbg
(
&
pmic_arb
->
spmic
->
dev
,
"intspec[0] 0x%1x intspec[1] 0x%02x intspec[2] 0x%02x
\n
"
,
intspec
[
0
],
intspec
[
1
],
intspec
[
2
]);
intspec
[
0
],
intspec
[
1
],
intspec
[
2
]);
if
(
irq_domain_get_of_node
(
d
)
!=
controller
)
if
(
irq_domain_get_of_node
(
d
)
!=
pmic_arb
->
spmic
->
dev
.
of_node
)
return
-
EINVAL
;
return
-
EINVAL
;
if
(
intsize
!=
4
)
if
(
fwspec
->
param_count
!=
4
)
return
-
EINVAL
;
return
-
EINVAL
;
if
(
intspec
[
0
]
>
0xF
||
intspec
[
1
]
>
0xFF
||
intspec
[
2
]
>
0x7
)
if
(
intspec
[
0
]
>
0xF
||
intspec
[
1
]
>
0xFF
||
intspec
[
2
]
>
0x7
)
return
-
EINVAL
;
return
-
EINVAL
;
...
@@ -740,17 +739,50 @@ static int qpnpint_irq_domain_dt_translate(struct irq_domain *d,
...
@@ -740,17 +739,50 @@ static int qpnpint_irq_domain_dt_translate(struct irq_domain *d,
return
0
;
return
0
;
}
}
static
int
qpnpint_irq_domain_map
(
struct
irq_domain
*
d
,
unsigned
int
virq
,
static
int
qpnpint_irq_domain_map
(
struct
spmi_pmic_arb
*
pmic_arb
,
irq_hw_number_t
hwirq
)
struct
irq_domain
*
domain
,
unsigned
int
virq
,
irq_hw_number_t
hwirq
,
unsigned
int
type
)
{
{
struct
spmi_pmic_arb
*
pmic_arb
=
d
->
host_data
;
irq_flow_handler_t
handler
;
dev_dbg
(
&
pmic_arb
->
spmic
->
dev
,
"virq = %u, hwirq = %lu, type = %u
\n
"
,
virq
,
hwirq
,
type
);
if
(
type
&
IRQ_TYPE_EDGE_BOTH
)
handler
=
handle_edge_irq
;
else
if
(
type
&
(
IRQ_TYPE_LEVEL_LOW
|
IRQ_TYPE_LEVEL_HIGH
))
handler
=
handle_level_irq
;
else
return
-
EINVAL
;
dev_dbg
(
&
pmic_arb
->
spmic
->
dev
,
"virq = %u, hwirq = %lu
\n
"
,
virq
,
hwirq
);
irq_domain_set_info
(
domain
,
virq
,
hwirq
,
&
pmic_arb_irqchip
,
pmic_arb
,
handler
,
NULL
,
NULL
);
return
0
;
}
static
int
qpnpint_irq_domain_alloc
(
struct
irq_domain
*
domain
,
unsigned
int
virq
,
unsigned
int
nr_irqs
,
void
*
data
)
{
struct
spmi_pmic_arb
*
pmic_arb
=
domain
->
host_data
;
struct
irq_fwspec
*
fwspec
=
data
;
irq_hw_number_t
hwirq
;
unsigned
int
type
;
int
ret
,
i
;
ret
=
qpnpint_irq_domain_translate
(
domain
,
fwspec
,
&
hwirq
,
&
type
);
if
(
ret
)
return
ret
;
for
(
i
=
0
;
i
<
nr_irqs
;
i
++
)
{
ret
=
qpnpint_irq_domain_map
(
pmic_arb
,
domain
,
virq
+
i
,
hwirq
+
i
,
type
);
if
(
ret
)
return
ret
;
}
irq_set_chip_and_handler
(
virq
,
&
pmic_arb_irqchip
,
handle_level_irq
);
irq_set_chip_data
(
virq
,
d
->
host_data
);
irq_set_noprobe
(
virq
);
return
0
;
return
0
;
}
}
...
@@ -1126,8 +1158,10 @@ static const struct pmic_arb_ver_ops pmic_arb_v5 = {
...
@@ -1126,8 +1158,10 @@ static const struct pmic_arb_ver_ops pmic_arb_v5 = {
};
};
static
const
struct
irq_domain_ops
pmic_arb_irq_domain_ops
=
{
static
const
struct
irq_domain_ops
pmic_arb_irq_domain_ops
=
{
.
map
=
qpnpint_irq_domain_map
,
.
activate
=
qpnpint_irq_domain_activate
,
.
xlate
=
qpnpint_irq_domain_dt_translate
,
.
alloc
=
qpnpint_irq_domain_alloc
,
.
free
=
irq_domain_free_irqs_common
,
.
translate
=
qpnpint_irq_domain_translate
,
};
};
static
int
spmi_pmic_arb_probe
(
struct
platform_device
*
pdev
)
static
int
spmi_pmic_arb_probe
(
struct
platform_device
*
pdev
)
...
...
include/linux/gpio/driver.h
View file @
4136e455
...
@@ -472,6 +472,11 @@ int gpiochip_irq_map(struct irq_domain *d, unsigned int irq,
...
@@ -472,6 +472,11 @@ int gpiochip_irq_map(struct irq_domain *d, unsigned int irq,
irq_hw_number_t
hwirq
);
irq_hw_number_t
hwirq
);
void
gpiochip_irq_unmap
(
struct
irq_domain
*
d
,
unsigned
int
irq
);
void
gpiochip_irq_unmap
(
struct
irq_domain
*
d
,
unsigned
int
irq
);
int
gpiochip_irq_domain_activate
(
struct
irq_domain
*
domain
,
struct
irq_data
*
data
,
bool
reserve
);
void
gpiochip_irq_domain_deactivate
(
struct
irq_domain
*
domain
,
struct
irq_data
*
data
);
void
gpiochip_set_chained_irqchip
(
struct
gpio_chip
*
gpiochip
,
void
gpiochip_set_chained_irqchip
(
struct
gpio_chip
*
gpiochip
,
struct
irq_chip
*
irqchip
,
struct
irq_chip
*
irqchip
,
unsigned
int
parent_irq
,
unsigned
int
parent_irq
,
...
...
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