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
89b0b4e2
Commit
89b0b4e2
authored
Mar 27, 2018
by
Linus Walleij
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'gpio-reserved-ranges' into devel
parents
6cb9215b
691bf5d5
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
167 additions
and
11 deletions
+167
-11
Documentation/devicetree/bindings/gpio/gpio.txt
Documentation/devicetree/bindings/gpio/gpio.txt
+4
-3
drivers/gpio/gpiolib-of.c
drivers/gpio/gpiolib-of.c
+24
-0
drivers/gpio/gpiolib.c
drivers/gpio/gpiolib.c
+61
-5
drivers/pinctrl/qcom/pinctrl-msm.c
drivers/pinctrl/qcom/pinctrl-msm.c
+62
-3
include/linux/gpio/driver.h
include/linux/gpio/driver.h
+16
-0
No files found.
Documentation/devicetree/bindings/gpio/gpio.txt
View file @
89b0b4e2
...
...
@@ -151,9 +151,9 @@ in a lot of designs, some using all 32 bits, some using 18 and some using
first 18 GPIOs, at local offset 0 .. 17, are in use.
If these GPIOs do not happen to be the first N GPIOs at offset 0...N-1, an
additional
bitmask is needed to specify which GPIOs are actually in use,
and which are dummies. The bindings for this case has not yet been
specified, but should be specified if/when such hardware appears
.
additional
set of tuples is needed to specify which GPIOs are unusable, with
the gpio-reserved-ranges binding. This property indicates the start and size
of the GPIOs that can't be used
.
Optionally, a GPIO controller may have a "gpio-line-names" property. This is
an array of strings defining the names of the GPIO lines going out of the
...
...
@@ -178,6 +178,7 @@ gpio-controller@00000000 {
gpio-controller;
#gpio-cells = <2>;
ngpios = <18>;
gpio-reserved-ranges = <0 4>, <12 2>;
gpio-line-names = "MMC-CD", "MMC-WP", "VDD eth", "RST eth", "LED R",
"LED G", "LED B", "Col A", "Col B", "Col C", "Col D",
"Row A", "Row B", "Row C", "Row D", "NMI button",
...
...
drivers/gpio/gpiolib-of.c
View file @
89b0b4e2
...
...
@@ -511,6 +511,28 @@ void of_mm_gpiochip_remove(struct of_mm_gpio_chip *mm_gc)
}
EXPORT_SYMBOL
(
of_mm_gpiochip_remove
);
static
void
of_gpiochip_init_valid_mask
(
struct
gpio_chip
*
chip
)
{
int
len
,
i
;
u32
start
,
count
;
struct
device_node
*
np
=
chip
->
of_node
;
len
=
of_property_count_u32_elems
(
np
,
"gpio-reserved-ranges"
);
if
(
len
<
0
||
len
%
2
!=
0
)
return
;
for
(
i
=
0
;
i
<
len
;
i
+=
2
)
{
of_property_read_u32_index
(
np
,
"gpio-reserved-ranges"
,
i
,
&
start
);
of_property_read_u32_index
(
np
,
"gpio-reserved-ranges"
,
i
+
1
,
&
count
);
if
(
start
>=
chip
->
ngpio
||
start
+
count
>=
chip
->
ngpio
)
continue
;
bitmap_clear
(
chip
->
valid_mask
,
start
,
count
);
}
};
#ifdef CONFIG_PINCTRL
static
int
of_gpiochip_add_pin_range
(
struct
gpio_chip
*
chip
)
{
...
...
@@ -615,6 +637,8 @@ int of_gpiochip_add(struct gpio_chip *chip)
if
(
chip
->
of_gpio_n_cells
>
MAX_PHANDLE_ARGS
)
return
-
EINVAL
;
of_gpiochip_init_valid_mask
(
chip
);
status
=
of_gpiochip_add_pin_range
(
chip
);
if
(
status
)
return
status
;
...
...
drivers/gpio/gpiolib.c
View file @
89b0b4e2
...
...
@@ -337,6 +337,57 @@ static int gpiochip_set_desc_names(struct gpio_chip *gc)
return
0
;
}
static
unsigned
long
*
gpiochip_allocate_mask
(
struct
gpio_chip
*
chip
)
{
unsigned
long
*
p
;
p
=
kmalloc_array
(
BITS_TO_LONGS
(
chip
->
ngpio
),
sizeof
(
*
p
),
GFP_KERNEL
);
if
(
!
p
)
return
NULL
;
/* Assume by default all GPIOs are valid */
bitmap_fill
(
p
,
chip
->
ngpio
);
return
p
;
}
static
int
gpiochip_init_valid_mask
(
struct
gpio_chip
*
gpiochip
)
{
#ifdef CONFIG_OF_GPIO
int
size
;
struct
device_node
*
np
=
gpiochip
->
of_node
;
size
=
of_property_count_u32_elems
(
np
,
"gpio-reserved-ranges"
);
if
(
size
>
0
&&
size
%
2
==
0
)
gpiochip
->
need_valid_mask
=
true
;
#endif
if
(
!
gpiochip
->
need_valid_mask
)
return
0
;
gpiochip
->
valid_mask
=
gpiochip_allocate_mask
(
gpiochip
);
if
(
!
gpiochip
->
valid_mask
)
return
-
ENOMEM
;
return
0
;
}
static
void
gpiochip_free_valid_mask
(
struct
gpio_chip
*
gpiochip
)
{
kfree
(
gpiochip
->
valid_mask
);
gpiochip
->
valid_mask
=
NULL
;
}
bool
gpiochip_line_is_valid
(
const
struct
gpio_chip
*
gpiochip
,
unsigned
int
offset
)
{
/* No mask means all valid */
if
(
likely
(
!
gpiochip
->
valid_mask
))
return
true
;
return
test_bit
(
offset
,
gpiochip
->
valid_mask
);
}
EXPORT_SYMBOL_GPL
(
gpiochip_line_is_valid
);
/*
* GPIO line handle management
*/
...
...
@@ -1261,6 +1312,10 @@ int gpiochip_add_data_with_key(struct gpio_chip *chip, void *data,
if
(
status
)
goto
err_remove_from_list
;
status
=
gpiochip_init_valid_mask
(
chip
);
if
(
status
)
goto
err_remove_irqchip_mask
;
status
=
gpiochip_add_irqchip
(
chip
,
lock_key
,
request_key
);
if
(
status
)
goto
err_remove_chip
;
...
...
@@ -1290,6 +1345,8 @@ int gpiochip_add_data_with_key(struct gpio_chip *chip, void *data,
acpi_gpiochip_remove
(
chip
);
gpiochip_free_hogs
(
chip
);
of_gpiochip_remove
(
chip
);
gpiochip_free_valid_mask
(
chip
);
err_remove_irqchip_mask:
gpiochip_irqchip_free_valid_mask
(
chip
);
err_remove_from_list:
spin_lock_irqsave
(
&
gpio_lock
,
flags
);
...
...
@@ -1346,6 +1403,7 @@ void gpiochip_remove(struct gpio_chip *chip)
acpi_gpiochip_remove
(
chip
);
gpiochip_remove_pin_ranges
(
chip
);
of_gpiochip_remove
(
chip
);
gpiochip_free_valid_mask
(
chip
);
/*
* We accept no more calls into the driver from this point, so
* NULL the driver data pointer
...
...
@@ -1506,14 +1564,10 @@ static int gpiochip_irqchip_init_valid_mask(struct gpio_chip *gpiochip)
if
(
!
gpiochip
->
irq
.
need_valid_mask
)
return
0
;
gpiochip
->
irq
.
valid_mask
=
kcalloc
(
BITS_TO_LONGS
(
gpiochip
->
ngpio
),
sizeof
(
long
),
GFP_KERNEL
);
gpiochip
->
irq
.
valid_mask
=
gpiochip_allocate_mask
(
gpiochip
);
if
(
!
gpiochip
->
irq
.
valid_mask
)
return
-
ENOMEM
;
/* Assume by default all GPIOs are valid */
bitmap_fill
(
gpiochip
->
irq
.
valid_mask
,
gpiochip
->
ngpio
);
return
0
;
}
...
...
@@ -1526,6 +1580,8 @@ static void gpiochip_irqchip_free_valid_mask(struct gpio_chip *gpiochip)
bool
gpiochip_irqchip_irq_valid
(
const
struct
gpio_chip
*
gpiochip
,
unsigned
int
offset
)
{
if
(
!
gpiochip_line_is_valid
(
gpiochip
,
offset
))
return
false
;
/* No mask means all valid */
if
(
likely
(
!
gpiochip
->
irq
.
valid_mask
))
return
true
;
...
...
drivers/pinctrl/qcom/pinctrl-msm.c
View file @
89b0b4e2
...
...
@@ -105,6 +105,14 @@ static const struct pinctrl_ops msm_pinctrl_ops = {
.
dt_free_map
=
pinctrl_utils_free_map
,
};
static
int
msm_pinmux_request
(
struct
pinctrl_dev
*
pctldev
,
unsigned
offset
)
{
struct
msm_pinctrl
*
pctrl
=
pinctrl_dev_get_drvdata
(
pctldev
);
struct
gpio_chip
*
chip
=
&
pctrl
->
chip
;
return
gpiochip_line_is_valid
(
chip
,
offset
)
?
0
:
-
EINVAL
;
}
static
int
msm_get_functions_count
(
struct
pinctrl_dev
*
pctldev
)
{
struct
msm_pinctrl
*
pctrl
=
pinctrl_dev_get_drvdata
(
pctldev
);
...
...
@@ -166,6 +174,7 @@ static int msm_pinmux_set_mux(struct pinctrl_dev *pctldev,
}
static
const
struct
pinmux_ops
msm_pinmux_ops
=
{
.
request
=
msm_pinmux_request
,
.
get_functions_count
=
msm_get_functions_count
,
.
get_function_name
=
msm_get_function_name
,
.
get_function_groups
=
msm_get_function_groups
,
...
...
@@ -506,6 +515,9 @@ static void msm_gpio_dbg_show_one(struct seq_file *s,
"pull up"
};
if
(
!
gpiochip_line_is_valid
(
chip
,
offset
))
return
;
g
=
&
pctrl
->
soc
->
groups
[
offset
];
ctl_reg
=
readl
(
pctrl
->
regs
+
g
->
ctl_reg
);
...
...
@@ -517,6 +529,7 @@ static void msm_gpio_dbg_show_one(struct seq_file *s,
seq_printf
(
s
,
" %-8s: %-3s %d"
,
g
->
name
,
is_out
?
"out"
:
"in"
,
func
);
seq_printf
(
s
,
" %dmA"
,
msm_regval_to_drive
(
drive
));
seq_printf
(
s
,
" %s"
,
pulls
[
pull
]);
seq_puts
(
s
,
"
\n
"
);
}
static
void
msm_gpio_dbg_show
(
struct
seq_file
*
s
,
struct
gpio_chip
*
chip
)
...
...
@@ -524,10 +537,8 @@ static void msm_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
unsigned
gpio
=
chip
->
base
;
unsigned
i
;
for
(
i
=
0
;
i
<
chip
->
ngpio
;
i
++
,
gpio
++
)
{
for
(
i
=
0
;
i
<
chip
->
ngpio
;
i
++
,
gpio
++
)
msm_gpio_dbg_show_one
(
s
,
NULL
,
chip
,
i
,
gpio
);
seq_puts
(
s
,
"
\n
"
);
}
}
#else
...
...
@@ -808,6 +819,46 @@ static void msm_gpio_irq_handler(struct irq_desc *desc)
chained_irq_exit
(
chip
,
desc
);
}
static
int
msm_gpio_init_valid_mask
(
struct
gpio_chip
*
chip
,
struct
msm_pinctrl
*
pctrl
)
{
int
ret
;
unsigned
int
len
,
i
;
unsigned
int
max_gpios
=
pctrl
->
soc
->
ngpios
;
u16
*
tmp
;
/* The number of GPIOs in the ACPI tables */
len
=
ret
=
device_property_read_u16_array
(
pctrl
->
dev
,
"gpios"
,
NULL
,
0
);
if
(
ret
<
0
)
return
0
;
if
(
ret
>
max_gpios
)
return
-
EINVAL
;
tmp
=
kmalloc_array
(
len
,
sizeof
(
*
tmp
),
GFP_KERNEL
);
if
(
!
tmp
)
return
-
ENOMEM
;
ret
=
device_property_read_u16_array
(
pctrl
->
dev
,
"gpios"
,
tmp
,
len
);
if
(
ret
<
0
)
{
dev_err
(
pctrl
->
dev
,
"could not read list of GPIOs
\n
"
);
goto
out
;
}
bitmap_zero
(
chip
->
valid_mask
,
max_gpios
);
for
(
i
=
0
;
i
<
len
;
i
++
)
set_bit
(
tmp
[
i
],
chip
->
valid_mask
);
out:
kfree
(
tmp
);
return
ret
;
}
static
bool
msm_gpio_needs_valid_mask
(
struct
msm_pinctrl
*
pctrl
)
{
return
device_property_read_u16_array
(
pctrl
->
dev
,
"gpios"
,
NULL
,
0
)
>
0
;
}
static
int
msm_gpio_init
(
struct
msm_pinctrl
*
pctrl
)
{
struct
gpio_chip
*
chip
;
...
...
@@ -824,6 +875,7 @@ static int msm_gpio_init(struct msm_pinctrl *pctrl)
chip
->
parent
=
pctrl
->
dev
;
chip
->
owner
=
THIS_MODULE
;
chip
->
of_node
=
pctrl
->
dev
->
of_node
;
chip
->
need_valid_mask
=
msm_gpio_needs_valid_mask
(
pctrl
);
ret
=
gpiochip_add_data
(
&
pctrl
->
chip
,
pctrl
);
if
(
ret
)
{
...
...
@@ -831,6 +883,13 @@ static int msm_gpio_init(struct msm_pinctrl *pctrl)
return
ret
;
}
ret
=
msm_gpio_init_valid_mask
(
chip
,
pctrl
);
if
(
ret
)
{
dev_err
(
pctrl
->
dev
,
"Failed to setup irq valid bits
\n
"
);
gpiochip_remove
(
&
pctrl
->
chip
);
return
ret
;
}
ret
=
gpiochip_add_pin_range
(
&
pctrl
->
chip
,
dev_name
(
pctrl
->
dev
),
0
,
0
,
chip
->
ngpio
);
if
(
ret
)
{
dev_err
(
pctrl
->
dev
,
"Failed to add pin range
\n
"
);
...
...
include/linux/gpio/driver.h
View file @
89b0b4e2
...
...
@@ -288,6 +288,21 @@ struct gpio_chip {
struct
gpio_irq_chip
irq
;
#endif
/**
* @need_valid_mask:
*
* If set core allocates @valid_mask with all bits set to one.
*/
bool
need_valid_mask
;
/**
* @valid_mask:
*
* If not %NULL holds bitmask of GPIOs which are valid to be used
* from the chip.
*/
unsigned
long
*
valid_mask
;
#if defined(CONFIG_OF_GPIO)
/*
* If CONFIG_OF is enabled, then all GPIO controllers described in the
...
...
@@ -384,6 +399,7 @@ bool gpiochip_line_is_open_source(struct gpio_chip *chip, unsigned int offset);
/* Sleep persistence inquiry for drivers */
bool
gpiochip_line_is_persistent
(
struct
gpio_chip
*
chip
,
unsigned
int
offset
);
bool
gpiochip_line_is_valid
(
const
struct
gpio_chip
*
chip
,
unsigned
int
offset
);
/* get driver data */
void
*
gpiochip_get_data
(
struct
gpio_chip
*
chip
);
...
...
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