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
3dda927f
Commit
3dda927f
authored
Feb 21, 2019
by
Linus Walleij
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'ib-qcom-ssbi' into devel
parents
9aac1e33
79890c2e
Changes
12
Hide whitespace changes
Inline
Side-by-side
Showing
12 changed files
with
236 additions
and
184 deletions
+236
-184
arch/arm/boot/dts/qcom-apq8060-dragonboard.dts
arch/arm/boot/dts/qcom-apq8060-dragonboard.dts
+8
-13
arch/arm/boot/dts/qcom-apq8064.dtsi
arch/arm/boot/dts/qcom-apq8064.dtsi
+2
-44
arch/arm/boot/dts/qcom-mdm9615.dtsi
arch/arm/boot/dts/qcom-mdm9615.dtsi
+2
-7
arch/arm/boot/dts/qcom-msm8660.dtsi
arch/arm/boot/dts/qcom-msm8660.dtsi
+2
-45
drivers/mfd/Kconfig
drivers/mfd/Kconfig
+1
-1
drivers/mfd/qcom-pm8xxx.c
drivers/mfd/qcom-pm8xxx.c
+38
-37
drivers/pinctrl/qcom/Kconfig
drivers/pinctrl/qcom/Kconfig
+1
-0
drivers/pinctrl/qcom/pinctrl-ssbi-gpio.c
drivers/pinctrl/qcom/pinctrl-ssbi-gpio.c
+131
-26
include/linux/irq.h
include/linux/irq.h
+1
-0
include/linux/irqdomain.h
include/linux/irqdomain.h
+5
-0
kernel/irq/chip.c
kernel/irq/chip.c
+11
-0
kernel/irq/irqdomain.c
kernel/irq/irqdomain.c
+34
-11
No files found.
arch/arm/boot/dts/qcom-apq8060-dragonboard.dts
View file @
3dda927f
...
...
@@ -93,9 +93,8 @@ cm3605 {
vdd
-
supply
=
<&
pm8058_l14
>;
//
2.85
V
aset
-
gpios
=
<&
pm8058_gpio
35
GPIO_ACTIVE_LOW
>;
capella
,
aset
-
resistance
-
ohms
=
<
100000
>;
/*
GPIO34
has
interrupt
225
on
the
PM8058
*/
/*
Trig
on
both
edges
-
getting
close
or
far
away
*/
interrupts
-
extended
=
<&
pm8058
225
IRQ_TYPE_EDGE_BOTH
>;
interrupts
-
extended
=
<&
pm8058
_gpio
34
IRQ_TYPE_EDGE_BOTH
>;
/*
MPP05
analog
input
to
the
XOADC
*/
io
-
channels
=
<&
xoadc
0x00
0x05
>;
io
-
channel
-
names
=
"aout"
;
...
...
@@ -515,9 +514,8 @@ i2c@19c80000 {
ak8975@c {
compatible = "asahi-kasei,ak8975";
reg = <0x0c>;
/* FIXME: GPIO33 has interrupt 224 on the PM8058 */
interrupt-parent = <&pm8058>;
interrupts = <224 IRQ_TYPE_EDGE_RISING>;
interrupt-parent = <&pm8058_gpio>;
interrupts = <33 IRQ_TYPE_EDGE_RISING>;
pinctrl-names = "default";
pinctrl-0 = <&dragon_ak8975_gpios>;
vid-supply = <&pm8058_lvs0>; // 1.8V
...
...
@@ -526,9 +524,8 @@ ak8975@c {
bmp085@77 {
compatible = "bosch,bmp085";
reg = <0x77>;
/* FIXME: GPIO16 has interrupt 207 on the PM8058 */
interrupt-parent = <&pm8058>;
interrupts = <207 IRQ_TYPE_EDGE_RISING>;
interrupt-parent = <&pm8058_gpio>;
interrupts = <16 IRQ_TYPE_EDGE_RISING>;
reset-gpios = <&tlmm 86 GPIO_ACTIVE_LOW>;
pinctrl-names = "default";
pinctrl-0 = <&dragon_bmp085_gpios>;
...
...
@@ -539,12 +536,11 @@ mpu3050@68 {
compatible = "invensense,mpu3050";
reg = <0x68>;
/*
* GPIO17 has interrupt 208 on the
* PM8058, it is pulled high by a 10k
* GPIO17 is pulled high by a 10k
* resistor to VLOGIC so needs to be
* active low/falling edge.
*/
interrupts-extended = <&pm8058
208
IRQ_TYPE_EDGE_FALLING>;
interrupts-extended = <&pm8058
_gpio 17
IRQ_TYPE_EDGE_FALLING>;
pinctrl-names = "default";
pinctrl-0 = <&dragon_mpu3050_gpios>;
vlogic-supply = <&pm8058_lvs0>; // 1.8V
...
...
@@ -589,11 +585,10 @@ ethernet-ebi2@2,0 {
compatible = "smsc,lan9221", "smsc,lan9115";
reg = <2 0x0 0x100>;
/*
* GPIO7 has interrupt 198 on the PM8058
* The second interrupt is the PME interrupt
* for network wakeup, connected to the TLMM.
*/
interrupts-extended = <&pm8058
198
IRQ_TYPE_EDGE_FALLING>,
interrupts-extended = <&pm8058
_gpio 7
IRQ_TYPE_EDGE_FALLING>,
<&tlmm 29 IRQ_TYPE_EDGE_RISING>;
reset-gpios = <&tlmm 30 GPIO_ACTIVE_LOW>;
vdd33a-supply = <&dragon_veth>;
...
...
arch/arm/boot/dts/qcom-apq8064.dtsi
View file @
3dda927f
...
...
@@ -705,50 +705,8 @@ pm8921_gpio: gpio@150 {
compatible
=
"qcom,pm8921-gpio"
,
"qcom,ssbi-gpio"
;
reg
=
<
0x150
>;
interrupts
=
<
192
IRQ_TYPE_NONE
>,
<
193
IRQ_TYPE_NONE
>,
<
194
IRQ_TYPE_NONE
>,
<
195
IRQ_TYPE_NONE
>,
<
196
IRQ_TYPE_NONE
>,
<
197
IRQ_TYPE_NONE
>,
<
198
IRQ_TYPE_NONE
>,
<
199
IRQ_TYPE_NONE
>,
<
200
IRQ_TYPE_NONE
>,
<
201
IRQ_TYPE_NONE
>,
<
202
IRQ_TYPE_NONE
>,
<
203
IRQ_TYPE_NONE
>,
<
204
IRQ_TYPE_NONE
>,
<
205
IRQ_TYPE_NONE
>,
<
206
IRQ_TYPE_NONE
>,
<
207
IRQ_TYPE_NONE
>,
<
208
IRQ_TYPE_NONE
>,
<
209
IRQ_TYPE_NONE
>,
<
210
IRQ_TYPE_NONE
>,
<
211
IRQ_TYPE_NONE
>,
<
212
IRQ_TYPE_NONE
>,
<
213
IRQ_TYPE_NONE
>,
<
214
IRQ_TYPE_NONE
>,
<
215
IRQ_TYPE_NONE
>,
<
216
IRQ_TYPE_NONE
>,
<
217
IRQ_TYPE_NONE
>,
<
218
IRQ_TYPE_NONE
>,
<
219
IRQ_TYPE_NONE
>,
<
220
IRQ_TYPE_NONE
>,
<
221
IRQ_TYPE_NONE
>,
<
222
IRQ_TYPE_NONE
>,
<
223
IRQ_TYPE_NONE
>,
<
224
IRQ_TYPE_NONE
>,
<
225
IRQ_TYPE_NONE
>,
<
226
IRQ_TYPE_NONE
>,
<
227
IRQ_TYPE_NONE
>,
<
228
IRQ_TYPE_NONE
>,
<
229
IRQ_TYPE_NONE
>,
<
230
IRQ_TYPE_NONE
>,
<
231
IRQ_TYPE_NONE
>,
<
232
IRQ_TYPE_NONE
>,
<
233
IRQ_TYPE_NONE
>,
<
234
IRQ_TYPE_NONE
>,
<
235
IRQ_TYPE_NONE
>;
interrupt
-
controller
;
#
interrupt
-
cells
=
<
2
>;
gpio
-
controller
;
#
gpio
-
cells
=
<
2
>;
...
...
arch/arm/boot/dts/qcom-mdm9615.dtsi
View file @
3dda927f
...
...
@@ -323,13 +323,8 @@ rtc@11d {
pmicgpio
:
gpio
@
150
{
compatible
=
"qcom,pm8018-gpio"
,
"qcom,ssbi-gpio"
;
interrupt
-
parent
=
<&
pmicintc
>;
interrupts
=
<
24
IRQ_TYPE_NONE
>,
<
25
IRQ_TYPE_NONE
>,
<
26
IRQ_TYPE_NONE
>,
<
27
IRQ_TYPE_NONE
>,
<
28
IRQ_TYPE_NONE
>,
<
29
IRQ_TYPE_NONE
>;
interrupt
-
controller
;
#
interrupt
-
cells
=
<
2
>;
gpio
-
controller
;
#
gpio
-
cells
=
<
2
>;
};
...
...
arch/arm/boot/dts/qcom-msm8660.dtsi
View file @
3dda927f
...
...
@@ -285,51 +285,8 @@ pm8058_gpio: gpio@150 {
compatible
=
"qcom,pm8058-gpio"
,
"qcom,ssbi-gpio"
;
reg
=
<
0x150
>;
interrupt
-
parent
=
<&
pm8058
>;
interrupts
=
<
192
IRQ_TYPE_NONE
>,
<
193
IRQ_TYPE_NONE
>,
<
194
IRQ_TYPE_NONE
>,
<
195
IRQ_TYPE_NONE
>,
<
196
IRQ_TYPE_NONE
>,
<
197
IRQ_TYPE_NONE
>,
<
198
IRQ_TYPE_NONE
>,
<
199
IRQ_TYPE_NONE
>,
<
200
IRQ_TYPE_NONE
>,
<
201
IRQ_TYPE_NONE
>,
<
202
IRQ_TYPE_NONE
>,
<
203
IRQ_TYPE_NONE
>,
<
204
IRQ_TYPE_NONE
>,
<
205
IRQ_TYPE_NONE
>,
<
206
IRQ_TYPE_NONE
>,
<
207
IRQ_TYPE_NONE
>,
<
208
IRQ_TYPE_NONE
>,
<
209
IRQ_TYPE_NONE
>,
<
210
IRQ_TYPE_NONE
>,
<
211
IRQ_TYPE_NONE
>,
<
212
IRQ_TYPE_NONE
>,
<
213
IRQ_TYPE_NONE
>,
<
214
IRQ_TYPE_NONE
>,
<
215
IRQ_TYPE_NONE
>,
<
216
IRQ_TYPE_NONE
>,
<
217
IRQ_TYPE_NONE
>,
<
218
IRQ_TYPE_NONE
>,
<
219
IRQ_TYPE_NONE
>,
<
220
IRQ_TYPE_NONE
>,
<
221
IRQ_TYPE_NONE
>,
<
222
IRQ_TYPE_NONE
>,
<
223
IRQ_TYPE_NONE
>,
<
224
IRQ_TYPE_NONE
>,
<
225
IRQ_TYPE_NONE
>,
<
226
IRQ_TYPE_NONE
>,
<
227
IRQ_TYPE_NONE
>,
<
228
IRQ_TYPE_NONE
>,
<
229
IRQ_TYPE_NONE
>,
<
230
IRQ_TYPE_NONE
>,
<
231
IRQ_TYPE_NONE
>,
<
232
IRQ_TYPE_NONE
>,
<
233
IRQ_TYPE_NONE
>,
<
234
IRQ_TYPE_NONE
>,
<
235
IRQ_TYPE_NONE
>;
interrupt
-
controller
;
#
interrupt
-
cells
=
<
2
>;
gpio
-
controller
;
#
gpio
-
cells
=
<
2
>;
...
...
drivers/mfd/Kconfig
View file @
3dda927f
...
...
@@ -928,7 +928,7 @@ config UCB1400_CORE
config MFD_PM8XXX
tristate "Qualcomm PM8xxx PMIC chips driver"
depends on (ARM || HEXAGON || COMPILE_TEST)
select IRQ_DOMAIN
select IRQ_DOMAIN
_HIERARCHY
select MFD_CORE
select REGMAP
help
...
...
drivers/mfd/qcom-pm8xxx.c
View file @
3dda927f
...
...
@@ -70,22 +70,23 @@
#define PM8XXX_NR_IRQS 256
#define PM8821_NR_IRQS 112
struct
pm_irq_data
{
int
num_irqs
;
struct
irq_chip
*
irq_chip
;
void
(
*
irq_handler
)(
struct
irq_desc
*
desc
);
};
struct
pm_irq_chip
{
struct
regmap
*
regmap
;
spinlock_t
pm_irq_lock
;
struct
irq_domain
*
irqdomain
;
unsigned
int
num_irqs
;
unsigned
int
num_blocks
;
unsigned
int
num_masters
;
const
struct
pm_irq_data
*
pm_irq_data
;
/* MUST BE AT THE END OF THIS STRUCT */
u8
config
[
0
];
};
struct
pm_irq_data
{
int
num_irqs
;
const
struct
irq_domain_ops
*
irq_domain_ops
;
void
(
*
irq_handler
)(
struct
irq_desc
*
desc
);
};
static
int
pm8xxx_read_block_irq
(
struct
pm_irq_chip
*
chip
,
unsigned
int
bp
,
unsigned
int
*
ip
)
{
...
...
@@ -375,21 +376,38 @@ static struct irq_chip pm8xxx_irq_chip = {
.
flags
=
IRQCHIP_MASK_ON_SUSPEND
|
IRQCHIP_SKIP_SET_WAKE
,
};
static
int
pm8xxx_irq_domain_map
(
struct
irq_domain
*
d
,
unsigned
int
irq
,
irq_hw_number_t
hwirq
)
static
void
pm8xxx_irq_domain_map
(
struct
pm_irq_chip
*
chip
,
struct
irq_domain
*
domain
,
unsigned
int
irq
,
irq_hw_number_t
hwirq
,
unsigned
int
type
)
{
struct
pm_irq_chip
*
chip
=
d
->
host_data
;
irq_set_chip_and_handler
(
irq
,
&
pm8xxx_irq_chip
,
handle_level_irq
);
irq_set_chip_data
(
irq
,
chip
);
irq_domain_set_info
(
domain
,
irq
,
hwirq
,
chip
->
pm_irq_data
->
irq_chip
,
chip
,
handle_level_irq
,
NULL
,
NULL
);
irq_set_noprobe
(
irq
);
}
static
int
pm8xxx_irq_domain_alloc
(
struct
irq_domain
*
domain
,
unsigned
int
virq
,
unsigned
int
nr_irqs
,
void
*
data
)
{
struct
pm_irq_chip
*
chip
=
domain
->
host_data
;
struct
irq_fwspec
*
fwspec
=
data
;
irq_hw_number_t
hwirq
;
unsigned
int
type
;
int
ret
,
i
;
ret
=
irq_domain_translate_twocell
(
domain
,
fwspec
,
&
hwirq
,
&
type
);
if
(
ret
)
return
ret
;
for
(
i
=
0
;
i
<
nr_irqs
;
i
++
)
pm8xxx_irq_domain_map
(
chip
,
domain
,
virq
+
i
,
hwirq
+
i
,
type
);
return
0
;
}
static
const
struct
irq_domain_ops
pm8xxx_irq_domain_ops
=
{
.
xlate
=
irq_domain_xlate_twocell
,
.
map
=
pm8xxx_irq_domain_map
,
.
alloc
=
pm8xxx_irq_domain_alloc
,
.
free
=
irq_domain_free_irqs_common
,
.
translate
=
irq_domain_translate_twocell
,
};
static
void
pm8821_irq_mask_ack
(
struct
irq_data
*
d
)
...
...
@@ -473,23 +491,6 @@ static struct irq_chip pm8821_irq_chip = {
.
flags
=
IRQCHIP_MASK_ON_SUSPEND
|
IRQCHIP_SKIP_SET_WAKE
,
};
static
int
pm8821_irq_domain_map
(
struct
irq_domain
*
d
,
unsigned
int
irq
,
irq_hw_number_t
hwirq
)
{
struct
pm_irq_chip
*
chip
=
d
->
host_data
;
irq_set_chip_and_handler
(
irq
,
&
pm8821_irq_chip
,
handle_level_irq
);
irq_set_chip_data
(
irq
,
chip
);
irq_set_noprobe
(
irq
);
return
0
;
}
static
const
struct
irq_domain_ops
pm8821_irq_domain_ops
=
{
.
xlate
=
irq_domain_xlate_twocell
,
.
map
=
pm8821_irq_domain_map
,
};
static
const
struct
regmap_config
ssbi_regmap_config
=
{
.
reg_bits
=
16
,
.
val_bits
=
8
,
...
...
@@ -501,13 +502,13 @@ static const struct regmap_config ssbi_regmap_config = {
static
const
struct
pm_irq_data
pm8xxx_data
=
{
.
num_irqs
=
PM8XXX_NR_IRQS
,
.
irq_
domain_ops
=
&
pm8xxx_irq_domain_ops
,
.
irq_
chip
=
&
pm8xxx_irq_chip
,
.
irq_handler
=
pm8xxx_irq_handler
,
};
static
const
struct
pm_irq_data
pm8821_data
=
{
.
num_irqs
=
PM8821_NR_IRQS
,
.
irq_
domain_ops
=
&
pm8821_irq_domain_ops
,
.
irq_
chip
=
&
pm8821_irq_chip
,
.
irq_handler
=
pm8821_irq_handler
,
};
...
...
@@ -571,14 +572,14 @@ static int pm8xxx_probe(struct platform_device *pdev)
platform_set_drvdata
(
pdev
,
chip
);
chip
->
regmap
=
regmap
;
chip
->
num_irqs
=
data
->
num_irqs
;
chip
->
num_blocks
=
DIV_ROUND_UP
(
chip
->
num_irqs
,
8
);
chip
->
num_blocks
=
DIV_ROUND_UP
(
data
->
num_irqs
,
8
);
chip
->
num_masters
=
DIV_ROUND_UP
(
chip
->
num_blocks
,
8
);
chip
->
pm_irq_data
=
data
;
spin_lock_init
(
&
chip
->
pm_irq_lock
);
chip
->
irqdomain
=
irq_domain_add_linear
(
pdev
->
dev
.
of_node
,
data
->
num_irqs
,
data
->
irq_domain_ops
,
&
pm8xxx_
irq_domain_ops
,
chip
);
if
(
!
chip
->
irqdomain
)
return
-
ENODEV
;
...
...
drivers/pinctrl/qcom/Kconfig
View file @
3dda927f
...
...
@@ -150,6 +150,7 @@ config PINCTRL_QCOM_SSBI_PMIC
select PINMUX
select PINCONF
select GENERIC_PINCONF
select IRQ_DOMAIN_HIERARCHY
help
This is the pinctrl, pinmux, pinconf and gpiolib driver for the
Qualcomm GPIO and MPP blocks found in the Qualcomm PMIC's chips,
...
...
drivers/pinctrl/qcom/pinctrl-ssbi-gpio.c
View file @
3dda927f
...
...
@@ -55,6 +55,8 @@
#define PM8XXX_MAX_GPIOS 44
#define PM8XXX_GPIO_PHYSICAL_OFFSET 1
/* custom pinconf parameters */
#define PM8XXX_QCOM_DRIVE_STRENGH (PIN_CONFIG_END + 1)
#define PM8XXX_QCOM_PULL_UP_STRENGTH (PIN_CONFIG_END + 2)
...
...
@@ -99,6 +101,9 @@ struct pm8xxx_gpio {
struct
pinctrl_desc
desc
;
unsigned
npins
;
struct
fwnode_handle
*
fwnode
;
struct
irq_domain
*
domain
;
};
static
const
struct
pinconf_generic_params
pm8xxx_gpio_bindings
[]
=
{
...
...
@@ -499,11 +504,12 @@ static int pm8xxx_gpio_get(struct gpio_chip *chip, unsigned offset)
if
(
pin
->
mode
==
PM8XXX_GPIO_MODE_OUTPUT
)
{
ret
=
pin
->
output_value
;
}
else
{
}
else
if
(
pin
->
irq
>=
0
)
{
ret
=
irq_get_irqchip_state
(
pin
->
irq
,
IRQCHIP_STATE_LINE_LEVEL
,
&
state
);
if
(
!
ret
)
ret
=
!!
state
;
}
}
else
ret
=
-
EINVAL
;
return
ret
;
}
...
...
@@ -533,16 +539,39 @@ static int pm8xxx_gpio_of_xlate(struct gpio_chip *chip,
if
(
flags
)
*
flags
=
gpio_desc
->
args
[
1
];
return
gpio_desc
->
args
[
0
]
-
1
;
return
gpio_desc
->
args
[
0
]
-
PM8XXX_GPIO_PHYSICAL_OFFSET
;
}
static
int
pm8xxx_gpio_to_irq
(
struct
gpio_chip
*
chip
,
unsigned
offset
)
{
struct
pm8xxx_gpio
*
pctrl
=
gpiochip_get_data
(
chip
);
struct
pm8xxx_pin_data
*
pin
=
pctrl
->
desc
.
pins
[
offset
].
drv_data
;
struct
irq_fwspec
fwspec
;
int
ret
;
fwspec
.
fwnode
=
pctrl
->
fwnode
;
fwspec
.
param_count
=
2
;
fwspec
.
param
[
0
]
=
offset
+
PM8XXX_GPIO_PHYSICAL_OFFSET
;
fwspec
.
param
[
1
]
=
IRQ_TYPE_EDGE_RISING
;
ret
=
irq_create_fwspec_mapping
(
&
fwspec
);
/*
* Cache the IRQ since pm8xxx_gpio_get() needs this to get determine the
* line level.
*/
pin
->
irq
=
ret
;
return
ret
;
}
static
void
pm8xxx_gpio_free
(
struct
gpio_chip
*
chip
,
unsigned
int
offset
)
{
struct
pm8xxx_gpio
*
pctrl
=
gpiochip_get_data
(
chip
);
struct
pm8xxx_pin_data
*
pin
=
pctrl
->
desc
.
pins
[
offset
].
drv_data
;
return
pin
->
irq
;
pin
->
irq
=
-
1
;
}
#ifdef CONFIG_DEBUG_FS
...
...
@@ -571,7 +600,7 @@ static void pm8xxx_gpio_dbg_show_one(struct seq_file *s,
"no"
,
"high"
,
"medium"
,
"low"
};
seq_printf
(
s
,
" gpio%-2d:"
,
offset
+
1
);
seq_printf
(
s
,
" gpio%-2d:"
,
offset
+
PM8XXX_GPIO_PHYSICAL_OFFSET
);
if
(
pin
->
disable
)
{
seq_puts
(
s
,
" ---"
);
}
else
{
...
...
@@ -603,6 +632,7 @@ static void pm8xxx_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
#endif
static
const
struct
gpio_chip
pm8xxx_gpio_template
=
{
.
free
=
pm8xxx_gpio_free
,
.
direction_input
=
pm8xxx_gpio_direction_input
,
.
direction_output
=
pm8xxx_gpio_direction_output
,
.
get
=
pm8xxx_gpio_get
,
...
...
@@ -664,13 +694,75 @@ static int pm8xxx_pin_populate(struct pm8xxx_gpio *pctrl,
return
0
;
}
static
struct
irq_chip
pm8xxx_irq_chip
=
{
.
name
=
"ssbi-gpio"
,
.
irq_mask_ack
=
irq_chip_mask_ack_parent
,
.
irq_unmask
=
irq_chip_unmask_parent
,
.
irq_set_type
=
irq_chip_set_type_parent
,
.
flags
=
IRQCHIP_MASK_ON_SUSPEND
|
IRQCHIP_SKIP_SET_WAKE
,
};
static
int
pm8xxx_domain_translate
(
struct
irq_domain
*
domain
,
struct
irq_fwspec
*
fwspec
,
unsigned
long
*
hwirq
,
unsigned
int
*
type
)
{
struct
pm8xxx_gpio
*
pctrl
=
container_of
(
domain
->
host_data
,
struct
pm8xxx_gpio
,
chip
);
if
(
fwspec
->
param_count
!=
2
||
fwspec
->
param
[
0
]
<
1
||
fwspec
->
param
[
0
]
>
pctrl
->
chip
.
ngpio
)
return
-
EINVAL
;
*
hwirq
=
fwspec
->
param
[
0
]
-
PM8XXX_GPIO_PHYSICAL_OFFSET
;
*
type
=
fwspec
->
param
[
1
];
return
0
;
}
static
int
pm8xxx_domain_alloc
(
struct
irq_domain
*
domain
,
unsigned
int
virq
,
unsigned
int
nr_irqs
,
void
*
data
)
{
struct
pm8xxx_gpio
*
pctrl
=
container_of
(
domain
->
host_data
,
struct
pm8xxx_gpio
,
chip
);
struct
irq_fwspec
*
fwspec
=
data
;
struct
irq_fwspec
parent_fwspec
;
irq_hw_number_t
hwirq
;
unsigned
int
type
;
int
ret
,
i
;
ret
=
pm8xxx_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
,
&
pm8xxx_irq_chip
,
pctrl
,
handle_level_irq
,
NULL
,
NULL
);
parent_fwspec
.
fwnode
=
domain
->
parent
->
fwnode
;
parent_fwspec
.
param_count
=
2
;
parent_fwspec
.
param
[
0
]
=
hwirq
+
0xc0
;
parent_fwspec
.
param
[
1
]
=
fwspec
->
param
[
1
];
return
irq_domain_alloc_irqs_parent
(
domain
,
virq
,
nr_irqs
,
&
parent_fwspec
);
}
static
const
struct
irq_domain_ops
pm8xxx_domain_ops
=
{
.
activate
=
gpiochip_irq_domain_activate
,
.
alloc
=
pm8xxx_domain_alloc
,
.
deactivate
=
gpiochip_irq_domain_deactivate
,
.
free
=
irq_domain_free_irqs_common
,
.
translate
=
pm8xxx_domain_translate
,
};
static
const
struct
of_device_id
pm8xxx_gpio_of_match
[]
=
{
{
.
compatible
=
"qcom,pm8018-gpio"
},
{
.
compatible
=
"qcom,pm8038-gpio"
},
{
.
compatible
=
"qcom,pm8058-gpio"
},
{
.
compatible
=
"qcom,pm8917-gpio"
},
{
.
compatible
=
"qcom,pm8921-gpio"
},
{
.
compatible
=
"qcom,ssbi-gpio"
},
{
.
compatible
=
"qcom,pm8018-gpio"
,
.
data
=
(
void
*
)
6
},
{
.
compatible
=
"qcom,pm8038-gpio"
,
.
data
=
(
void
*
)
12
},
{
.
compatible
=
"qcom,pm8058-gpio"
,
.
data
=
(
void
*
)
44
},
{
.
compatible
=
"qcom,pm8917-gpio"
,
.
data
=
(
void
*
)
38
},
{
.
compatible
=
"qcom,pm8921-gpio"
,
.
data
=
(
void
*
)
44
},
{
},
};
MODULE_DEVICE_TABLE
(
of
,
pm8xxx_gpio_of_match
);
...
...
@@ -678,22 +770,18 @@ MODULE_DEVICE_TABLE(of, pm8xxx_gpio_of_match);
static
int
pm8xxx_gpio_probe
(
struct
platform_device
*
pdev
)
{
struct
pm8xxx_pin_data
*
pin_data
;
struct
irq_domain
*
parent_domain
;
struct
device_node
*
parent_node
;
struct
pinctrl_pin_desc
*
pins
;
struct
pm8xxx_gpio
*
pctrl
;
int
ret
;
int
i
,
npins
;
int
ret
,
i
;
pctrl
=
devm_kzalloc
(
&
pdev
->
dev
,
sizeof
(
*
pctrl
),
GFP_KERNEL
);
if
(
!
pctrl
)
return
-
ENOMEM
;
pctrl
->
dev
=
&
pdev
->
dev
;
npins
=
platform_irq_count
(
pdev
);
if
(
!
npins
)
return
-
EINVAL
;
if
(
npins
<
0
)
return
npins
;
pctrl
->
npins
=
npins
;
pctrl
->
npins
=
(
uintptr_t
)
device_get_match_data
(
&
pdev
->
dev
);
pctrl
->
regmap
=
dev_get_regmap
(
pdev
->
dev
.
parent
,
NULL
);
if
(
!
pctrl
->
regmap
)
{
...
...
@@ -720,12 +808,7 @@ static int pm8xxx_gpio_probe(struct platform_device *pdev)
for
(
i
=
0
;
i
<
pctrl
->
desc
.
npins
;
i
++
)
{
pin_data
[
i
].
reg
=
SSBI_REG_ADDR_GPIO
(
i
);
pin_data
[
i
].
irq
=
platform_get_irq
(
pdev
,
i
);
if
(
pin_data
[
i
].
irq
<
0
)
{
dev_err
(
&
pdev
->
dev
,
"missing interrupts for pin %d
\n
"
,
i
);
return
pin_data
[
i
].
irq
;
}
pin_data
[
i
].
irq
=
-
1
;
ret
=
pm8xxx_pin_populate
(
pctrl
,
&
pin_data
[
i
]);
if
(
ret
)
...
...
@@ -756,10 +839,29 @@ static int pm8xxx_gpio_probe(struct platform_device *pdev)
pctrl
->
chip
.
of_gpio_n_cells
=
2
;
pctrl
->
chip
.
label
=
dev_name
(
pctrl
->
dev
);
pctrl
->
chip
.
ngpio
=
pctrl
->
npins
;
parent_node
=
of_irq_find_parent
(
pctrl
->
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
;
pctrl
->
fwnode
=
of_node_to_fwnode
(
pctrl
->
dev
->
of_node
);
pctrl
->
domain
=
irq_domain_create_hierarchy
(
parent_domain
,
0
,
pctrl
->
chip
.
ngpio
,
pctrl
->
fwnode
,
&
pm8xxx_domain_ops
,
&
pctrl
->
chip
);
if
(
!
pctrl
->
domain
)
return
-
ENODEV
;
ret
=
gpiochip_add_data
(
&
pctrl
->
chip
,
pctrl
);
if
(
ret
)
{
dev_err
(
&
pdev
->
dev
,
"failed register gpiochip
\n
"
);
return
ret
;
goto
err_chip_add_data
;
}
/*
...
...
@@ -789,6 +891,8 @@ static int pm8xxx_gpio_probe(struct platform_device *pdev)
unregister_gpiochip:
gpiochip_remove
(
&
pctrl
->
chip
);
err_chip_add_data:
irq_domain_remove
(
pctrl
->
domain
);
return
ret
;
}
...
...
@@ -798,6 +902,7 @@ static int pm8xxx_gpio_remove(struct platform_device *pdev)
struct
pm8xxx_gpio
*
pctrl
=
platform_get_drvdata
(
pdev
);
gpiochip_remove
(
&
pctrl
->
chip
);
irq_domain_remove
(
pctrl
->
domain
);
return
0
;
}
...
...
include/linux/irq.h
View file @
3dda927f
...
...
@@ -605,6 +605,7 @@ extern void irq_chip_disable_parent(struct irq_data *data);
extern
void
irq_chip_ack_parent
(
struct
irq_data
*
data
);
extern
int
irq_chip_retrigger_hierarchy
(
struct
irq_data
*
data
);
extern
void
irq_chip_mask_parent
(
struct
irq_data
*
data
);
extern
void
irq_chip_mask_ack_parent
(
struct
irq_data
*
data
);
extern
void
irq_chip_unmask_parent
(
struct
irq_data
*
data
);
extern
void
irq_chip_eoi_parent
(
struct
irq_data
*
data
);
extern
int
irq_chip_set_affinity_parent
(
struct
irq_data
*
data
,
...
...
include/linux/irqdomain.h
View file @
3dda927f
...
...
@@ -419,6 +419,11 @@ int irq_domain_xlate_onetwocell(struct irq_domain *d, struct device_node *ctrlr,
const
u32
*
intspec
,
unsigned
int
intsize
,
irq_hw_number_t
*
out_hwirq
,
unsigned
int
*
out_type
);
int
irq_domain_translate_twocell
(
struct
irq_domain
*
d
,
struct
irq_fwspec
*
fwspec
,
unsigned
long
*
out_hwirq
,
unsigned
int
*
out_type
);
/* IPI functions */
int
irq_reserve_ipi
(
struct
irq_domain
*
domain
,
const
struct
cpumask
*
dest
);
int
irq_destroy_ipi
(
unsigned
int
irq
,
const
struct
cpumask
*
dest
);
...
...
kernel/irq/chip.c
View file @
3dda927f
...
...
@@ -1277,6 +1277,17 @@ void irq_chip_mask_parent(struct irq_data *data)
}
EXPORT_SYMBOL_GPL
(
irq_chip_mask_parent
);
/**
* irq_chip_mask_ack_parent - Mask and acknowledge the parent interrupt
* @data: Pointer to interrupt specific data
*/
void
irq_chip_mask_ack_parent
(
struct
irq_data
*
data
)
{
data
=
data
->
parent_data
;
data
->
chip
->
irq_mask_ack
(
data
);
}
EXPORT_SYMBOL_GPL
(
irq_chip_mask_ack_parent
);
/**
* irq_chip_unmask_parent - Unmask the parent interrupt
* @data: Pointer to interrupt specific data
...
...
kernel/irq/irqdomain.c
View file @
3dda927f
...
...
@@ -729,16 +729,17 @@ static int irq_domain_translate(struct irq_domain *d,
return
0
;
}
static
void
of_phandle_args_to_fwspec
(
struct
of_phandle_args
*
irq_data
,
static
void
of_phandle_args_to_fwspec
(
struct
device_node
*
np
,
const
u32
*
args
,
unsigned
int
count
,
struct
irq_fwspec
*
fwspec
)
{
int
i
;
fwspec
->
fwnode
=
irq_data
->
np
?
&
irq_data
->
np
->
fwnode
:
NULL
;
fwspec
->
param_count
=
irq_data
->
args_
count
;
fwspec
->
fwnode
=
np
?
&
np
->
fwnode
:
NULL
;
fwspec
->
param_count
=
count
;
for
(
i
=
0
;
i
<
irq_data
->
args_
count
;
i
++
)
fwspec
->
param
[
i
]
=
irq_data
->
args
[
i
];
for
(
i
=
0
;
i
<
count
;
i
++
)
fwspec
->
param
[
i
]
=
args
[
i
];
}
unsigned
int
irq_create_fwspec_mapping
(
struct
irq_fwspec
*
fwspec
)
...
...
@@ -836,7 +837,9 @@ unsigned int irq_create_of_mapping(struct of_phandle_args *irq_data)
{
struct
irq_fwspec
fwspec
;
of_phandle_args_to_fwspec
(
irq_data
,
&
fwspec
);
of_phandle_args_to_fwspec
(
irq_data
->
np
,
irq_data
->
args
,
irq_data
->
args_count
,
&
fwspec
);
return
irq_create_fwspec_mapping
(
&
fwspec
);
}
EXPORT_SYMBOL_GPL
(
irq_create_of_mapping
);
...
...
@@ -928,11 +931,10 @@ int irq_domain_xlate_twocell(struct irq_domain *d, struct device_node *ctrlr,
const
u32
*
intspec
,
unsigned
int
intsize
,
irq_hw_number_t
*
out_hwirq
,
unsigned
int
*
out_type
)
{
if
(
WARN_ON
(
intsize
<
2
))
return
-
EINVAL
;
*
out_hwirq
=
intspec
[
0
];
*
out_type
=
intspec
[
1
]
&
IRQ_TYPE_SENSE_MASK
;
return
0
;
struct
irq_fwspec
fwspec
;
of_phandle_args_to_fwspec
(
ctrlr
,
intspec
,
intsize
,
&
fwspec
);
return
irq_domain_translate_twocell
(
d
,
&
fwspec
,
out_hwirq
,
out_type
);
}
EXPORT_SYMBOL_GPL
(
irq_domain_xlate_twocell
);
...
...
@@ -968,6 +970,27 @@ const struct irq_domain_ops irq_domain_simple_ops = {
};
EXPORT_SYMBOL_GPL
(
irq_domain_simple_ops
);
/**
* irq_domain_translate_twocell() - Generic translate for direct two cell
* bindings
*
* Device Tree IRQ specifier translation function which works with two cell
* bindings where the cell values map directly to the hwirq number
* and linux irq flags.
*/
int
irq_domain_translate_twocell
(
struct
irq_domain
*
d
,
struct
irq_fwspec
*
fwspec
,
unsigned
long
*
out_hwirq
,
unsigned
int
*
out_type
)
{
if
(
WARN_ON
(
fwspec
->
param_count
<
2
))
return
-
EINVAL
;
*
out_hwirq
=
fwspec
->
param
[
0
];
*
out_type
=
fwspec
->
param
[
1
]
&
IRQ_TYPE_SENSE_MASK
;
return
0
;
}
EXPORT_SYMBOL_GPL
(
irq_domain_translate_twocell
);
int
irq_domain_alloc_descs
(
int
virq
,
unsigned
int
cnt
,
irq_hw_number_t
hwirq
,
int
node
,
const
struct
irq_affinity_desc
*
affinity
)
{
...
...
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