Commit 20d5ba49 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'pinctrl-v4.10-1' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-pinctrl

Pull pinctrl updates from Linus Walleij:
 "Bulk pin control changes for the v4.10 kernel cycle:

  No core changes this time. Mainly gradual improvement and
  feature growth in the drivers.

  New drivers:

   - New driver for TI DA850/OMAP-L138/AM18XX pinconf

   - The SX150x was moved over from the GPIO subsystem and reimagined as
     a pin control driver with GPIO support in a joint effort by three
     independent users of this hardware. The result was amazingly good!

   - New subdriver for the Oxnas OX820

  Improvements:

   - The sunxi driver now supports the generic pin control bindings
     rather than the sunxi-specific. Add debouncing support to the
     driver.

   - Simplifications in pinctrl-single adding a generic parser.

   - Two downstream fixes and move the Raspberry Pi BCM2835 over to use
     the generic GPIOLIB_IRQCHIP"

* tag 'pinctrl-v4.10-1' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-pinctrl: (92 commits)
  pinctrl: sx150x: use new nested IRQ infrastructure
  pinctrl: sx150x: handle missing 'advanced' reg in sx1504 and sx1505
  pinctrl: sx150x: rename 'reg_advance' to 'reg_advanced'
  pinctrl: sx150x: access the correct bits in the 4-bit regs of sx150[147]
  pinctrl: mt8173: set GPIO16 to usb iddig mode
  pinctrl: bcm2835: switch to GPIOLIB_IRQCHIP
  pinctrl: New driver for TI DA850/OMAP-L138/AM18XX pinconf
  devicetree: bindings: pinctrl: Add binding for ti,da850-pupd
  Documentation: pinctrl: palmas: Add ti,palmas-powerhold-override property definition
  pinctrl: intel: set default handler to be handle_bad_irq()
  pinctrl: sx150x: add support for sx1501, sx1504, sx1505 and sx1507
  pinctrl: sx150x: sort chips by part number
  pinctrl: sx150x: use correct registers for reg_sense (sx1502 and sx1508)
  pinctrl: imx: fix imx_pinctrl_desc initialization
  pinctrl: sx150x: support setting multiple pins at once
  pinctrl: sx150x: various spelling fixes and some white-space cleanup
  pinctrl: mediatek: use builtin_platform_driver
  pinctrl: stm32: use builtin_platform_driver
  pinctrl: sunxi: Testing the wrong variable
  pinctrl: nomadik: split up and comments MC0 pins
  ...
parents 061ad503 f8214445
......@@ -3,7 +3,7 @@
Please refer to gpio.txt for generic information regarding GPIO bindings.
Required properties:
- compatible: "oxsemi,ox810se-gpio"
- compatible: "oxsemi,ox810se-gpio" or "oxsemi,ox820-gpio"
- reg: Base address and length for the device.
- interrupts: The port interrupt shared by all pins.
- gpio-controller: Marks the port as GPIO controller.
......
......@@ -28,6 +28,20 @@ Required properties:
- reg: Should contain the register physical address and length for the
pin controller.
- clocks: phandle to the clocks feeding the pin controller:
- "apb": the gated APB parent clock
- "hosc": the high frequency oscillator in the system
- "losc": the low frequency oscillator in the system
Note: For backward compatibility reasons, the hosc and losc clocks are only
required if you need to use the optional input-debounce property. Any new
device tree should set them.
Optional properties:
- input-debounce: Array of debouncing periods in microseconds. One period per
irq bank found in the controller. 0 if no setup required.
Please refer to pinctrl-bindings.txt in this directory for details of the
common pinctrl bindings used by client devices.
......@@ -37,6 +51,22 @@ pins it needs, and how they should be configured, with regard to muxer
configuration, drive strength and pullups. If one of these options is
not set, its actual value will be unspecified.
This driver supports the generic pin multiplexing and configuration
bindings. For details on each properties, you can refer to
./pinctrl-bindings.txt.
Required sub-node properties:
- pins
- function
Optional sub-node properties:
- bias-disable
- bias-pull-up
- bias-pull-down
- drive-strength
*** Deprecated pin configuration and multiplexing binding
Required subnode-properties:
- allwinner,pins: List of strings containing the pin name.
......
......@@ -98,6 +98,8 @@ DRIVE_STRENGTH (3 << 5): indicate the drive strength of the pin using the
01 - Low
10 - Medium
11 - High
OUTPUT (1 << 7): indicate this pin need to be configured as an output.
OUTPUT_VAL (1 << 8): output val (1 = high, 0 = low)
DEBOUNCE (1 << 16): indicate this pin needs debounce.
DEBOUNCE_VAL (0x3fff << 17): debounce value.
......
......@@ -7,6 +7,8 @@ Required properties for the root node:
"amlogic,meson8b-aobus-pinctrl"
"amlogic,meson-gxbb-periphs-pinctrl"
"amlogic,meson-gxbb-aobus-pinctrl"
"amlogic,meson-gxl-periphs-pinctrl"
"amlogic,meson-gxl-aobus-pinctrl"
- reg: address and size of registers controlling irq functionality
=== GPIO sub-nodes ===
......
......@@ -9,7 +9,7 @@ used for a specific device or function. This node represents configurations of
pins, optional function, and optional mux related configuration.
Required properties for pin controller node:
- compatible: "oxsemi,ox810se-pinctrl"
- compatible: "oxsemi,ox810se-pinctrl" or "oxsemi,ox820-pinctrl"
- oxsemi,sys-ctrl: a phandle to the system controller syscon node
Required properties for pin configuration sub-nodes:
......
......@@ -97,6 +97,11 @@ For example:
};
== Pin controller devices ==
Required properties: See the pin controller driver specific documentation
Optional properties:
#pinctrl-cells: Number of pin control cells in addition to the index within the
pin controller device instance
Pin controller devices should contain the pin configuration nodes that client
devices reference.
......@@ -119,7 +124,8 @@ For example:
The contents of each of those pin configuration child nodes is defined
entirely by the binding for the individual pin controller device. There
exists no common standard for this content.
exists no common standard for this content. The pinctrl framework only
provides generic helper bindings that the pin controller driver can use.
The pin configuration nodes need not be direct children of the pin controller
device; they may be grandchildren, for example. Whether this is legal, and
......@@ -156,6 +162,42 @@ state_2_node_a {
pins = "mfio29", "mfio30";
};
Optionally an altenative binding can be used if more suitable depending on the
pin controller hardware. For hardaware where there is a large number of identical
pin controller instances, naming each pin and function can easily become
unmaintainable. This is especially the case if the same controller is used for
different pins and functions depending on the SoC revision and packaging.
For cases like this, the pin controller driver may use pinctrl-pin-array helper
binding with a hardware based index and a number of pin configuration values:
pincontroller {
... /* Standard DT properties for the device itself elided */
#pinctrl-cells = <2>;
state_0_node_a {
pinctrl-pin-array = <
0 A_DELAY_PS(0) G_DELAY_PS(120)
4 A_DELAY_PS(0) G_DELAY_PS(360)
...
>;
};
...
};
Above #pinctrl-cells specifies the number of value cells in addition to the
index of the registers. This is similar to the interrupts-extended binding with
one exception. There is no need to specify the phandle for each entry as that
is already known as the defined pins are always children of the pin controller
node. Further having the phandle pointing to another pin controller would not
currently work as the pinctrl framework uses named modes to group pins for each
pin control device.
The index for pinctrl-pin-array must relate to the hardware for the pinctrl
registers, and must not be a virtual index of pin instances. The reason for
this is to avoid mapping of the index in the dts files and the pin controller
driver as it can change.
== Generic pin configuration node content ==
Many data items that are represented in a pin configuration node are common
......
......@@ -35,6 +35,15 @@ Optional properties:
- ti,palmas-enable-dvfs2: Enable DVFS2. Configure pins for DVFS2 mode.
Selection primary or secondary function associated to GPADC_START
and SYSEN2 pin/pad for DVFS2 interface
- ti,palmas-override-powerhold: This is applicable for PMICs for which
GPIO7 is configured in POWERHOLD mode which has higher priority
over DEV_ON bit and keeps the PMIC supplies on even after the DEV_ON
bit is turned off. This property enables driver to over ride the
POWERHOLD value to GPIO7 so as to turn off the PMIC in power off
scenarios. So for GPIO7 if ti,palmas-override-powerhold is set
then the GPIO_7 field should never be muxed to anything else.
It should be set to POWERHOLD by default and only in case of
power off scenarios the driver will over ride the mux value.
This binding uses the following generic properties as defined in
pinctrl-bindings.txt:
......
......@@ -6,10 +6,15 @@ pin controller, GPIO, and interrupt bindings.
Required properties:
- compatible: should be one of :
"semtech,sx1501q",
"semtech,sx1502q",
"semtech,sx1503q",
"semtech,sx1504q",
"semtech,sx1505q",
"semtech,sx1506q",
"semtech,sx1507q",
"semtech,sx1508q",
"semtech,sx1509q",
"semtech,sx1502q".
"semtech,sx1509q".
- reg: The I2C slave address for this device.
......@@ -27,7 +32,7 @@ Optional properties :
- interrupt-controller: Marks the device as a interrupt controller.
- semtech,probe-reset: Will trigger a reset of the GPIO expander on probe,
only for sx1508q and sx1509q
only for sx1507q, sx1508q and sx1509q
The GPIO expander can optionally be used as an interrupt controller, in
which case it uses the default two cell specifier.
......@@ -42,7 +47,7 @@ Optional properties for pin configuration sub-nodes:
- bias-pull-down: pull down the pin, except the OSCIO pin
- bias-pull-pin-default: use pin-default pull state, except the OSCIO pin
- drive-push-pull: drive actively high and low
- drive-open-drain: drive with open drain only for sx1508q and sx1509q and except the OSCIO pin
- drive-open-drain: drive with open drain only for sx1507q, sx1508q and sx1509q and except the OSCIO pin
- output-low: set the pin to output mode with low level
- output-high: set the pin to output mode with high level
......
Qualcomm MSM8994 TLMM block
This binding describes the Top Level Mode Multiplexer block found in the
MSM8994 platform.
- compatible:
Usage: required
Value type: <string>
Definition: Should contain one of:
"qcom,msm8992-pinctrl",
"qcom,msm8994-pinctrl".
- reg:
Usage: required
Value type: <prop-encoded-array>
Definition: the base address and size of the TLMM register space.
- interrupts:
Usage: required
Value type: <prop-encoded-array>
Definition: should specify the TLMM summary IRQ.
- interrupt-controller:
Usage: required
Value type: <none>
Definition: identifies this node as an interrupt controller
- #interrupt-cells:
Usage: required
Value type: <u32>
Definition: must be 2. Specifying the pin number and flags, as defined
in <dt-bindings/interrupt-controller/irq.h>
- gpio-controller:
Usage: required
Value type: <none>
Definition: identifies this node as a gpio controller
- #gpio-cells:
Usage: required
Value type: <u32>
Definition: must be 2. Specifying the pin number and flags, as defined
in <dt-bindings/gpio/gpio.h>
Please refer to ../gpio/gpio.txt and ../interrupt-controller/interrupts.txt for
a general description of GPIO and interrupt bindings.
Please refer to pinctrl-bindings.txt in this directory for details of the
common pinctrl bindings used by client devices, including the meaning of the
phrase "pin configuration node".
The pin configuration nodes act as a container for an arbitrary number of
subnodes. Each of these subnodes represents some desired configuration for a
pin, a group, or a list of pins or groups. This configuration can include the
mux function to select on those pin(s)/group(s), and various pin configuration
parameters, such as pull-up, drive strength, etc.
PIN CONFIGURATION NODES:
The name of each subnode is not important; all subnodes should be enumerated
and processed purely based on their content.
Each subnode only affects those parameters that are explicitly listed. In
other words, a subnode that lists a mux function but no pin configuration
parameters implies no information about any pin configuration parameters.
Similarly, a pin subnode that describes a pullup parameter implies no
information about e.g. the mux function.
The following generic properties as defined in pinctrl-bindings.txt are valid
to specify in a pin configuration subnode:
- pins:
Usage: required
Value type: <string-array>
Definition: List of gpio pins affected by the properties specified in
this subnode.
Valid pins are:
gpio0-gpio145
Supports mux, bias and drive-strength
sdc1_clk, sdc1_cmd, sdc1_data sdc1_rclk, sdc2_clk,
sdc2_cmd, sdc2_data
Supports bias and drive-strength
- function:
Usage: required
Value type: <string>
Definition: Specify the alternative function to be configured for the
specified pins. Functions are only valid for gpio pins.
Valid values are:
audio_ref_clk, blsp_i2c1, blsp_i2c2, blsp_i2c3, blsp_i2c4, blsp_i2c5,
blsp_i2c6, blsp_i2c7, blsp_i2c8, blsp_i2c9, blsp_i2c10, blsp_i2c11,
blsp_i2c12, blsp_spi1, blsp_spi1_cs1, blsp_spi1_cs2, blsp_spi1_cs3,
blsp_spi2, blsp_spi2_cs1, blsp_spi2_cs2, blsp_spi2_cs3, blsp_spi3,
blsp_spi4, blsp_spi5, blsp_spi6, blsp_spi7, blsp_spi8, blsp_spi9,
blsp_spi10, blsp_spi10_cs1, blsp_spi10_cs2, blsp_spi10_cs3, blsp_spi11,
blsp_spi12, blsp_uart1, blsp_uart2, blsp_uart3, blsp_uart4, blsp_uart5,
blsp_uart6, blsp_uart7, blsp_uart8, blsp_uart9, blsp_uart10, blsp_uart11,
blsp_uart12, blsp_uim1, blsp_uim2, blsp_uim3, blsp_uim4, blsp_uim5,
blsp_uim6, blsp_uim7, blsp_uim8, blsp_uim9, blsp_uim10, blsp_uim11,
blsp_uim12, blsp11_i2c_scl_b, blsp11_i2c_sda_b, blsp11_uart_rx_b,
blsp11_uart_tx_b, cam_mclk0, cam_mclk1, cam_mclk2, cam_mclk3,
cci_async_in0, cci_async_in1, cci_async_in2, cci_i2c0, cci_i2c1,
cci_timer0, cci_timer1, cci_timer2, cci_timer3, cci_timer4,
gcc_gp1_clk_a, gcc_gp1_clk_b, gcc_gp2_clk_a, gcc_gp2_clk_b, gcc_gp3_clk_a,
gcc_gp3_clk_b, gp_mn, gp_pdm0, gp_pdm1, gp_pdm2, gp0_clk,
gp1_clk, gps_tx, gsm_tx, hdmi_cec, hdmi_ddc, hdmi_hpd, hdmi_rcv,
mdp_vsync, mss_lte, nav_pps, nav_tsync, qdss_cti_trig_in_a,
qdss_cti_trig_in_b, qdss_cti_trig_in_c, qdss_cti_trig_in_d,
qdss_cti_trig_out_a, qdss_cti_trig_out_b, qdss_cti_trig_out_c,
qdss_cti_trig_out_d, qdss_traceclk_a, qdss_traceclk_b, qdss_tracectl_a,
qdss_tracectl_b, qdss_tracedata_a, qdss_tracedata_b, qua_mi2s, pci_e0,
pci_e1, pri_mi2s, sdc4, sec_mi2s, slimbus, spkr_i2s, ter_mi2s, tsif1,
tsif2, uim_batt_alarm, uim1, uim2, uim3, uim4, gpio
- bias-disable:
Usage: optional
Value type: <none>
Definition: The specified pins should be configued as no pull.
- bias-pull-down:
Usage: optional
Value type: <none>
Definition: The specified pins should be configued as pull down.
- bias-pull-up:
Usage: optional
Value type: <none>
Definition: The specified pins should be configued as pull up.
- output-high:
Usage: optional
Value type: <none>
Definition: The specified pins are configured in output mode, driven
high.
Not valid for sdc pins.
- output-low:
Usage: optional
Value type: <none>
Definition: The specified pins are configured in output mode, driven
low.
Not valid for sdc pins.
- drive-strength:
Usage: optional
Value type: <u32>
Definition: Selects the drive strength for the specified pins, in mA.
Valid values are: 2, 4, 6, 8, 10, 12, 14 and 16
Example:
msmgpio: pinctrl@fd510000 {
compatible = "qcom,msm8994-pinctrl";
reg = <0xfd510000 0x4000>;
interrupts = <GIC_SPI 208 IRQ_TYPE_LEVEL_HIGH>;
gpio-controller;
#gpio-cells = <2>;
interrupt-controller;
#interrupt-cells = <2>;
blsp1_uart2_default: blsp1_uart2_default {
pinmux {
pins = "gpio4", "gpio5";
function = "blsp_uart2";
};
pinconf {
pins = "gpio4", "gpio5";
drive-strength = <16>;
bias-disable;
};
};
};
......@@ -19,10 +19,11 @@ The pins are grouped into up to 5 individual pin banks which need to be
defined as gpio sub-nodes of the pinmux controller.
Required properties for iomux controller:
- compatible: one of "rockchip,rk2928-pinctrl", "rockchip,rk3066a-pinctrl"
"rockchip,rk3066b-pinctrl", "rockchip,rk3188-pinctrl"
"rockchip,rk3228-pinctrl", "rockchip,rk3288-pinctrl"
"rockchip,rk3368-pinctrl", "rockchip,rk3399-pinctrl"
- compatible: one of "rockchip,rk1108-pinctrl", "rockchip,rk2928-pinctrl"
"rockchip,rk3066a-pinctrl", "rockchip,rk3066b-pinctrl"
"rockchip,rk3188-pinctrl", "rockchip,rk3228-pinctrl"
"rockchip,rk3288-pinctrl", "rockchip,rk3368-pinctrl"
"rockchip,rk3399-pinctrl"
- rockchip,grf: phandle referencing a syscon providing the
"general register files"
......
......@@ -19,11 +19,30 @@ Required Properties:
- "samsung,exynos5260-pinctrl": for Exynos5260 compatible pin-controller.
- "samsung,exynos5410-pinctrl": for Exynos5410 compatible pin-controller.
- "samsung,exynos5420-pinctrl": for Exynos5420 compatible pin-controller.
- "samsung,exynos5433-pinctrl": for Exynos5433 compatible pin-controller.
- "samsung,exynos7-pinctrl": for Exynos7 compatible pin-controller.
- reg: Base address of the pin controller hardware module and length of
the address space it occupies.
- reg: Second base address of the pin controller if the specific registers
of the pin controller are separated into the different base address.
Eg: GPF[1-5] of Exynos5433 are separated into the two base address.
- First base address is for GPAx and GPF[1-5] external interrupt
registers.
- Second base address is for GPF[1-5] pinctrl registers.
pinctrl_0: pinctrl@10580000 {
compatible = "samsung,exynos5433-pinctrl";
reg = <0x10580000 0x1a20>, <0x11090000 0x100>;
wakeup-interrupt-controller {
compatible = "samsung,exynos7-wakeup-eint";
interrupts = <0 16 0>;
};
};
- Pin banks as child nodes: Pin banks of the controller are represented by child
nodes of the controller node. Bank name is taken from name of the node. Each
bank node must contain following properties:
......
* Pin configuration for TI DA850/OMAP-L138/AM18x
These SoCs have a separate controller for setting bias (internal pullup/down).
Bias can only be selected for groups rather than individual pins.
Required Properties:
- compatible: Must be "ti,da850-pupd"
- reg: Base address and length of the memory resource used by the pullup/down
controller hardware module.
The controller node also acts as a container for pin group configuration nodes.
The names of these groups are ignored.
Pin Group Node Properties:
- groups: An array of strings, each string containing the name of a pin group.
Valid names are "cp0".."cp31".
The pin configuration parameters use the generic pinconf bindings defined in
pinctrl-bindings.txt in this directory. The supported parameters are
bias-disable, bias-pull-up, bias-pull-down.
Example
-------
In common dtsi file:
pinconf: pin-controller@22c00c {
compatible = "ti,da850-pupd";
reg = <0x22c00c 0x8>;
};
In board-specific file:
&pinconf {
pinctrl-0 = <&pinconf_bias_groups>;
pinctrl-names = "default";
pinconf_bias_groups: bias-groups {
pull-up {
groups = "cp30", "cp31";
bias-pull-up;
};
pull-down {
groups = "cp29", "cp28";
bias-pull-down;
};
disable {
groups = "cp27", "cp26";
bias-disable;
};
};
};
......@@ -93,6 +93,15 @@ config PINCTRL_AMD
Requires ACPI/FDT device enumeration code to set up a platform
device.
config PINCTRL_DA850_PUPD
tristate "TI DA850/OMAP-L138/AM18XX pullup/pulldown groups"
depends on OF && (ARCH_DAVINCI_DA850 || COMPILE_TEST)
select PINCONF
select GENERIC_PINCONF
help
Driver for TI DA850/OMAP-L138/AM18XX pinconf. Used to control
pullup/pulldown pin groups.
config PINCTRL_DIGICOLOR
bool
depends on OF && (ARCH_DIGICOLOR || COMPILE_TEST)
......@@ -171,6 +180,7 @@ config PINCTRL_SX150X
select PINCONF
select GENERIC_PINCONF
select GPIOLIB_IRQCHIP
select REGMAP
help
Say yes here to provide support for Semtech SX150x-series I2C
GPIO expanders as pinctrl module.
......@@ -223,7 +233,7 @@ config PINCTRL_COH901
config PINCTRL_MAX77620
tristate "MAX77620/MAX20024 Pincontrol support"
depends on MFD_MAX77620
depends on MFD_MAX77620 && OF
select PINMUX
select GENERIC_PINCONF
help
......
......@@ -14,6 +14,7 @@ obj-$(CONFIG_PINCTRL_BF60x) += pinctrl-adi2-bf60x.o
obj-$(CONFIG_PINCTRL_AT91) += pinctrl-at91.o
obj-$(CONFIG_PINCTRL_AT91PIO4) += pinctrl-at91-pio4.o
obj-$(CONFIG_PINCTRL_AMD) += pinctrl-amd.o
obj-$(CONFIG_PINCTRL_DA850_PUPD) += pinctrl-da850-pupd.o
obj-$(CONFIG_PINCTRL_DIGICOLOR) += pinctrl-digicolor.o
obj-$(CONFIG_PINCTRL_FALCON) += pinctrl-falcon.o
obj-$(CONFIG_PINCTRL_MAX77620) += pinctrl-max77620.o
......
......@@ -20,6 +20,7 @@ config PINCTRL_BCM2835
bool
select PINMUX
select PINCONF
select GPIOLIB_IRQCHIP
config PINCTRL_IPROC_GPIO
bool "Broadcom iProc GPIO (with PINCONF) driver"
......
This diff is collapsed.
......@@ -253,3 +253,147 @@ int pinctrl_dt_to_map(struct pinctrl *p)
pinctrl_dt_free_maps(p);
return ret;
}
/*
* For pinctrl binding, typically #pinctrl-cells is for the pin controller
* device, so either parent or grandparent. See pinctrl-bindings.txt.
*/
static int pinctrl_find_cells_size(const struct device_node *np)
{
const char *cells_name = "#pinctrl-cells";
int cells_size, error;
error = of_property_read_u32(np->parent, cells_name, &cells_size);
if (error) {
error = of_property_read_u32(np->parent->parent,
cells_name, &cells_size);
if (error)
return -ENOENT;
}
return cells_size;
}
/**
* pinctrl_get_list_and_count - Gets the list and it's cell size and number
* @np: pointer to device node with the property
* @list_name: property that contains the list
* @list: pointer for the list found
* @cells_size: pointer for the cell size found
* @nr_elements: pointer for the number of elements found
*
* Typically np is a single pinctrl entry containing the list.
*/
static int pinctrl_get_list_and_count(const struct device_node *np,
const char *list_name,
const __be32 **list,
int *cells_size,
int *nr_elements)
{
int size;
*cells_size = 0;
*nr_elements = 0;
*list = of_get_property(np, list_name, &size);
if (!*list)
return -ENOENT;
*cells_size = pinctrl_find_cells_size(np);
if (*cells_size < 0)
return -ENOENT;
/* First element is always the index within the pinctrl device */
*nr_elements = (size / sizeof(**list)) / (*cells_size + 1);
return 0;
}
/**
* pinctrl_count_index_with_args - Count number of elements in a pinctrl entry
* @np: pointer to device node with the property
* @list_name: property that contains the list
*
* Counts the number of elements in a pinctrl array consisting of an index
* within the controller and a number of u32 entries specified for each
* entry. Note that device_node is always for the parent pin controller device.
*/
int pinctrl_count_index_with_args(const struct device_node *np,
const char *list_name)
{
const __be32 *list;
int size, nr_cells, error;
error = pinctrl_get_list_and_count(np, list_name, &list,
&nr_cells, &size);
if (error)
return error;
return size;
}
EXPORT_SYMBOL_GPL(pinctrl_count_index_with_args);
/**
* pinctrl_copy_args - Populates of_phandle_args based on index
* @np: pointer to device node with the property
* @list: pointer to a list with the elements
* @index: entry within the list of elements
* @nr_cells: number of cells in the list
* @nr_elem: number of elements for each entry in the list
* @out_args: returned values
*
* Populates the of_phandle_args based on the index in the list.
*/
static int pinctrl_copy_args(const struct device_node *np,
const __be32 *list,
int index, int nr_cells, int nr_elem,
struct of_phandle_args *out_args)
{
int i;
memset(out_args, 0, sizeof(*out_args));
out_args->np = (struct device_node *)np;
out_args->args_count = nr_cells + 1;
if (index >= nr_elem)
return -EINVAL;
list += index * (nr_cells + 1);
for (i = 0; i < nr_cells + 1; i++)
out_args->args[i] = be32_to_cpup(list++);
return 0;
}
/**
* pinctrl_parse_index_with_args - Find a node pointed by index in a list
* @np: pointer to device node with the property
* @list_name: property that contains the list
* @index: index within the list
* @out_arts: entries in the list pointed by index
*
* Finds the selected element in a pinctrl array consisting of an index
* within the controller and a number of u32 entries specified for each
* entry. Note that device_node is always for the parent pin controller device.
*/
int pinctrl_parse_index_with_args(const struct device_node *np,
const char *list_name, int index,
struct of_phandle_args *out_args)
{
const __be32 *list;
int nr_elem, nr_cells, error;
error = pinctrl_get_list_and_count(np, list_name, &list,
&nr_cells, &nr_elem);
if (error || !nr_cells)
return error;
error = pinctrl_copy_args(np, list, index, nr_cells, nr_elem,
out_args);
if (error)
return error;
return 0;
}
EXPORT_SYMBOL_GPL(pinctrl_parse_index_with_args);
......@@ -16,11 +16,20 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
struct of_phandle_args;
#ifdef CONFIG_OF
void pinctrl_dt_free_maps(struct pinctrl *p);
int pinctrl_dt_to_map(struct pinctrl *p);
int pinctrl_count_index_with_args(const struct device_node *np,
const char *list_name);
int pinctrl_parse_index_with_args(const struct device_node *np,
const char *list_name, int index,
struct of_phandle_args *out_args);
#else
static inline int pinctrl_dt_to_map(struct pinctrl *p)
......@@ -32,4 +41,18 @@ static inline void pinctrl_dt_free_maps(struct pinctrl *p)
{
}
static inline int pinctrl_count_index_with_args(const struct device_node *np,
const char *list_name)
{
return -ENODEV;
}
static inline int
pinctrl_parse_index_with_args(const struct device_node *np,
const char *list_name, int index,
struct of_phandle_args *out_args)
{
return -ENODEV;
}
#endif
......@@ -778,10 +778,10 @@ int imx_pinctrl_probe(struct platform_device *pdev,
imx_pinctrl_desc->name = dev_name(&pdev->dev);
imx_pinctrl_desc->pins = info->pins;
imx_pinctrl_desc->npins = info->npins;
imx_pinctrl_desc->pctlops = &imx_pctrl_ops,
imx_pinctrl_desc->pmxops = &imx_pmx_ops,
imx_pinctrl_desc->confops = &imx_pinconf_ops,
imx_pinctrl_desc->owner = THIS_MODULE,
imx_pinctrl_desc->pctlops = &imx_pctrl_ops;
imx_pinctrl_desc->pmxops = &imx_pmx_ops;
imx_pinctrl_desc->confops = &imx_pinconf_ops;
imx_pinctrl_desc->owner = THIS_MODULE;
ret = imx_pinctrl_probe_dt(pdev, info);
if (ret) {
......
......@@ -1703,7 +1703,7 @@ static int byt_gpio_probe(struct byt_gpio *vg)
if (irq_rc && irq_rc->start) {
byt_gpio_irq_init_hw(vg);
ret = gpiochip_irqchip_add(gc, &byt_irqchip, 0,
handle_simple_irq, IRQ_TYPE_NONE);
handle_bad_irq, IRQ_TYPE_NONE);
if (ret) {
dev_err(&vg->pdev->dev, "failed to add irqchip\n");
goto fail;
......
......@@ -762,7 +762,7 @@ static void chv_pin_dbg_show(struct pinctrl_dev *pctldev, struct seq_file *s,
seq_printf(s, "mode %d ", mode);
}
seq_printf(s, "ctrl0 0x%08x ctrl1 0x%08x", ctrl0, ctrl1);
seq_printf(s, "0x%08x 0x%08x", ctrl0, ctrl1);
if (locked)
seq_puts(s, " [LOCKED]");
......
......@@ -911,7 +911,7 @@ static int intel_gpio_probe(struct intel_pinctrl *pctrl, int irq)
}
ret = gpiochip_irqchip_add(&pctrl->chip, &intel_gpio_irqchip, 0,
handle_simple_irq, IRQ_TYPE_NONE);
handle_bad_irq, IRQ_TYPE_NONE);
if (ret) {
dev_err(pctrl->dev, "failed to add irqchip\n");
goto fail;
......
......@@ -814,10 +814,51 @@ static int mrfld_config_set(struct pinctrl_dev *pctldev, unsigned int pin,
return 0;
}
static int mrfld_config_group_get(struct pinctrl_dev *pctldev,
unsigned int group, unsigned long *config)
{
const unsigned int *pins;
unsigned int npins;
int ret;
ret = mrfld_get_group_pins(pctldev, group, &pins, &npins);
if (ret)
return ret;
ret = mrfld_config_get(pctldev, pins[0], config);
if (ret)
return ret;
return 0;
}
static int mrfld_config_group_set(struct pinctrl_dev *pctldev,
unsigned int group, unsigned long *configs,
unsigned int num_configs)
{
const unsigned int *pins;
unsigned int npins;
int i, ret;
ret = mrfld_get_group_pins(pctldev, group, &pins, &npins);
if (ret)
return ret;
for (i = 0; i < npins; i++) {
ret = mrfld_config_set(pctldev, pins[i], configs, num_configs);
if (ret)
return ret;
}
return 0;
}
static const struct pinconf_ops mrfld_pinconf_ops = {
.is_generic = true,
.pin_config_get = mrfld_config_get,
.pin_config_set = mrfld_config_set,
.pin_config_group_get = mrfld_config_group_get,
.pin_config_group_set = mrfld_config_group_set,
};
static const struct pinctrl_desc mrfld_pinctrl_desc = {
......
......@@ -64,8 +64,4 @@ static struct platform_driver mtk_pinctrl_driver = {
},
};
static int __init mtk_pinctrl_init(void)
{
return platform_driver_register(&mtk_pinctrl_driver);
}
device_initcall(mtk_pinctrl_init);
builtin_platform_driver(mtk_pinctrl_driver);
......@@ -201,7 +201,7 @@ static const struct mtk_desc_pin mtk_pins_mt8173[] = {
MTK_PIN(
PINCTRL_PIN(16, "IDDIG"),
NULL, "mt8173",
MTK_EINT_FUNCTION(0, 16),
MTK_EINT_FUNCTION(1, 16),
MTK_FUNCTION(0, "GPIO16"),
MTK_FUNCTION(1, "IDDIG"),
MTK_FUNCTION(2, "CMFLASH"),
......
obj-y += pinctrl-meson8.o pinctrl-meson8b.o pinctrl-meson-gxbb.o
obj-y += pinctrl-meson8.o pinctrl-meson8b.o
obj-y += pinctrl-meson-gxbb.o pinctrl-meson-gxl.o
obj-y += pinctrl-meson.o
This diff is collapsed.
......@@ -524,6 +524,14 @@ static const struct of_device_id meson_pinctrl_dt_match[] = {
.compatible = "amlogic,meson-gxbb-aobus-pinctrl",
.data = &meson_gxbb_aobus_pinctrl_data,
},
{
.compatible = "amlogic,meson-gxl-periphs-pinctrl",
.data = &meson_gxl_periphs_pinctrl_data,
},
{
.compatible = "amlogic,meson-gxl-aobus-pinctrl",
.data = &meson_gxl_aobus_pinctrl_data,
},
{ },
};
......
......@@ -169,3 +169,5 @@ extern struct meson_pinctrl_data meson8b_cbus_pinctrl_data;
extern struct meson_pinctrl_data meson8b_aobus_pinctrl_data;
extern struct meson_pinctrl_data meson_gxbb_periphs_pinctrl_data;
extern struct meson_pinctrl_data meson_gxbb_aobus_pinctrl_data;
extern struct meson_pinctrl_data meson_gxl_periphs_pinctrl_data;
extern struct meson_pinctrl_data meson_gxl_aobus_pinctrl_data;
......@@ -379,13 +379,24 @@ static const unsigned msp0txrx_a_1_pins[] = { DB8500_PIN_AC4, DB8500_PIN_AC3 };
static const unsigned msp0tfstck_a_1_pins[] = { DB8500_PIN_AF3, DB8500_PIN_AE3 };
static const unsigned msp0rfsrck_a_1_pins[] = { DB8500_PIN_AD3, DB8500_PIN_AD4 };
/* Basic pins of the MMC/SD card 0 interface */
static const unsigned mc0_a_1_pins[] = { DB8500_PIN_AC2, DB8500_PIN_AC1,
DB8500_PIN_AB4, DB8500_PIN_AA3, DB8500_PIN_AA4, DB8500_PIN_AB2,
DB8500_PIN_Y4, DB8500_PIN_Y2, DB8500_PIN_AA2, DB8500_PIN_AA1 };
static const unsigned mc0_a_1_pins[] = { DB8500_PIN_AC2, /* MC0_CMDDIR */
DB8500_PIN_AC1, /* MC0_DAT0DIR */
DB8500_PIN_AB4, /* MC0_DAT2DIR */
DB8500_PIN_AA3, /* MC0_FBCLK */
DB8500_PIN_AA4, /* MC0_CLK */
DB8500_PIN_AB2, /* MC0_CMD */
DB8500_PIN_Y4, /* MC0_DAT0 */
DB8500_PIN_Y2, /* MC0_DAT1 */
DB8500_PIN_AA2, /* MC0_DAT2 */
DB8500_PIN_AA1 /* MC0_DAT3 */
};
/* Often only 4 bits are used, then these are not needed (only used for MMC) */
static const unsigned mc0_dat47_a_1_pins[] = { DB8500_PIN_W2, DB8500_PIN_W3,
DB8500_PIN_V3, DB8500_PIN_V2};
static const unsigned mc0dat31dir_a_1_pins[] = { DB8500_PIN_AB3 };
static const unsigned mc0_dat47_a_1_pins[] = { DB8500_PIN_W2, /* MC0_DAT4 */
DB8500_PIN_W3, /* MC0_DAT5 */
DB8500_PIN_V3, /* MC0_DAT6 */
DB8500_PIN_V2 /* MC0_DAT7 */
};
static const unsigned mc0dat31dir_a_1_pins[] = { DB8500_PIN_AB3 }; /* MC0_DAT31DIR */
/* MSP1 can only be on these pins, but TXD and RXD can be flipped */
static const unsigned msp1txrx_a_1_pins[] = { DB8500_PIN_AF2, DB8500_PIN_AG2 };
static const unsigned msp1_a_1_pins[] = { DB8500_PIN_AE1, DB8500_PIN_AE2 };
......
......@@ -381,7 +381,7 @@ int pinconf_generic_dt_node_to_map(struct pinctrl_dev *pctldev,
if (ret < 0)
goto exit;
for_each_child_of_node(np_config, np) {
for_each_available_child_of_node(np_config, np) {
ret = pinconf_generic_dt_subnode_to_map(pctldev, np, map,
&reserved_maps, num_maps, type);
if (ret < 0)
......
......@@ -56,6 +56,9 @@ static int gpio_banks;
#define DRIVE_STRENGTH_SHIFT 5
#define DRIVE_STRENGTH_MASK 0x3
#define DRIVE_STRENGTH (DRIVE_STRENGTH_MASK << DRIVE_STRENGTH_SHIFT)
#define OUTPUT (1 << 7)
#define OUTPUT_VAL_SHIFT 8
#define OUTPUT_VAL (0x1 << OUTPUT_VAL_SHIFT)
#define DEBOUNCE (1 << 16)
#define DEBOUNCE_VAL_SHIFT 17
#define DEBOUNCE_VAL (0x3fff << DEBOUNCE_VAL_SHIFT)
......@@ -375,6 +378,19 @@ static void at91_mux_set_pullup(void __iomem *pio, unsigned mask, bool on)
writel_relaxed(mask, pio + (on ? PIO_PUER : PIO_PUDR));
}
static bool at91_mux_get_output(void __iomem *pio, unsigned int pin, bool *val)
{
*val = (readl_relaxed(pio + PIO_ODSR) >> pin) & 0x1;
return (readl_relaxed(pio + PIO_OSR) >> pin) & 0x1;
}
static void at91_mux_set_output(void __iomem *pio, unsigned int mask,
bool is_on, bool val)
{
writel_relaxed(mask, pio + (val ? PIO_SODR : PIO_CODR));
writel_relaxed(mask, pio + (is_on ? PIO_OER : PIO_ODR));
}
static unsigned at91_mux_get_multidrive(void __iomem *pio, unsigned pin)
{
return (readl_relaxed(pio + PIO_MDSR) >> pin) & 0x1;
......@@ -848,6 +864,7 @@ static int at91_pinconf_get(struct pinctrl_dev *pctldev,
void __iomem *pio;
unsigned pin;
int div;
bool out;
*config = 0;
dev_dbg(info->dev, "%s:%d, pin_id=%d", __func__, __LINE__, pin_id);
......@@ -875,6 +892,8 @@ static int at91_pinconf_get(struct pinctrl_dev *pctldev,
if (info->ops->get_drivestrength)
*config |= (info->ops->get_drivestrength(pio, pin)
<< DRIVE_STRENGTH_SHIFT);
if (at91_mux_get_output(pio, pin, &out))
*config |= OUTPUT | (out << OUTPUT_VAL_SHIFT);
return 0;
}
......@@ -907,6 +926,8 @@ static int at91_pinconf_set(struct pinctrl_dev *pctldev,
if (config & PULL_UP && config & PULL_DOWN)
return -EINVAL;
at91_mux_set_output(pio, mask, config & OUTPUT,
(config & OUTPUT_VAL) >> OUTPUT_VAL_SHIFT);
at91_mux_set_pullup(pio, mask, config & PULL_UP);
at91_mux_set_multidrive(pio, mask, config & MULTI_DRIVE);
if (info->ops->set_deglitch)
......
/*
* Pinconf driver for TI DA850/OMAP-L138/AM18XX pullup/pulldown groups
*
* Copyright (C) 2016 David Lechner
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation; version 2 of the License.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*/
#include <linux/bitops.h>
#include <linux/device.h>
#include <linux/io.h>
#include <linux/ioport.h>
#include <linux/mod_devicetable.h>
#include <linux/module.h>
#include <linux/pinctrl/pinconf.h>
#include <linux/pinctrl/pinconf-generic.h>
#include <linux/pinctrl/pinctrl.h>
#include <linux/platform_device.h>
#define DA850_PUPD_ENA 0x00
#define DA850_PUPD_SEL 0x04
struct da850_pupd_data {
void __iomem *base;
struct pinctrl_desc desc;
struct pinctrl_dev *pinctrl;
};
static const char * const da850_pupd_group_names[] = {
"cp0", "cp1", "cp2", "cp3", "cp4", "cp5", "cp6", "cp7",
"cp8", "cp9", "cp10", "cp11", "cp12", "cp13", "cp14", "cp15",
"cp16", "cp17", "cp18", "cp19", "cp20", "cp21", "cp22", "cp23",
"cp24", "cp25", "cp26", "cp27", "cp28", "cp29", "cp30", "cp31",
};
static int da850_pupd_get_groups_count(struct pinctrl_dev *pctldev)
{
return ARRAY_SIZE(da850_pupd_group_names);
}
static const char *da850_pupd_get_group_name(struct pinctrl_dev *pctldev,
unsigned int selector)
{
return da850_pupd_group_names[selector];
}
static int da850_pupd_get_group_pins(struct pinctrl_dev *pctldev,
unsigned int selector,
const unsigned int **pins,
unsigned int *num_pins)
{
*num_pins = 0;
return 0;
}
static const struct pinctrl_ops da850_pupd_pctlops = {
.get_groups_count = da850_pupd_get_groups_count,
.get_group_name = da850_pupd_get_group_name,
.get_group_pins = da850_pupd_get_group_pins,
.dt_node_to_map = pinconf_generic_dt_node_to_map_group,
.dt_free_map = pinconf_generic_dt_free_map,
};
static int da850_pupd_pin_config_group_get(struct pinctrl_dev *pctldev,
unsigned int selector,
unsigned long *config)
{
struct da850_pupd_data *data = pinctrl_dev_get_drvdata(pctldev);
enum pin_config_param param = pinconf_to_config_param(*config);
u32 val;
u16 arg;
val = readl(data->base + DA850_PUPD_ENA);
arg = !!(~val & BIT(selector));
switch (param) {
case PIN_CONFIG_BIAS_DISABLE:
break;
case PIN_CONFIG_BIAS_PULL_UP:
case PIN_CONFIG_BIAS_PULL_DOWN:
if (arg) {
/* bias is disabled */
arg = 0;
break;
}
val = readl(data->base + DA850_PUPD_SEL);
if (param == PIN_CONFIG_BIAS_PULL_DOWN)
val = ~val;
arg = !!(val & BIT(selector));
break;
default:
return -EINVAL;
}
*config = pinconf_to_config_packed(param, arg);
return 0;
}
static int da850_pupd_pin_config_group_set(struct pinctrl_dev *pctldev,
unsigned int selector,
unsigned long *configs,
unsigned int num_configs)
{
struct da850_pupd_data *data = pinctrl_dev_get_drvdata(pctldev);
u32 ena, sel;
enum pin_config_param param;
u16 arg;
int i;
ena = readl(data->base + DA850_PUPD_ENA);
sel = readl(data->base + DA850_PUPD_SEL);
for (i = 0; i < num_configs; i++) {
param = pinconf_to_config_param(configs[i]);
arg = pinconf_to_config_argument(configs[i]);
switch (param) {
case PIN_CONFIG_BIAS_DISABLE:
ena &= ~BIT(selector);
break;
case PIN_CONFIG_BIAS_PULL_UP:
ena |= BIT(selector);
sel |= BIT(selector);
break;
case PIN_CONFIG_BIAS_PULL_DOWN:
ena |= BIT(selector);
sel &= ~BIT(selector);
break;
default:
return -EINVAL;
}
}
writel(sel, data->base + DA850_PUPD_SEL);
writel(ena, data->base + DA850_PUPD_ENA);
return 0;
}
static const struct pinconf_ops da850_pupd_confops = {
.is_generic = true,
.pin_config_group_get = da850_pupd_pin_config_group_get,
.pin_config_group_set = da850_pupd_pin_config_group_set,
};
static int da850_pupd_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct da850_pupd_data *data;
struct resource *res;
data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
if (!data)
return -ENOMEM;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
data->base = devm_ioremap_resource(dev, res);
if (IS_ERR(data->base)) {
dev_err(dev, "Could not map resource\n");
return PTR_ERR(data->base);
}
data->desc.name = dev_name(dev);
data->desc.pctlops = &da850_pupd_pctlops;
data->desc.confops = &da850_pupd_confops;
data->desc.owner = THIS_MODULE;
data->pinctrl = devm_pinctrl_register(dev, &data->desc, data);
if (IS_ERR(data->pinctrl)) {
dev_err(dev, "Failed to register pinctrl\n");
return PTR_ERR(data->pinctrl);
}
platform_set_drvdata(pdev, data);
return 0;
}
static int da850_pupd_remove(struct platform_device *pdev)
{
return 0;
}
static const struct of_device_id da850_pupd_of_match[] = {
{ .compatible = "ti,da850-pupd" },
{ }
};
static struct platform_driver da850_pupd_driver = {
.driver = {
.name = "ti-da850-pupd",
.of_match_table = da850_pupd_of_match,
},
.probe = da850_pupd_probe,
.remove = da850_pupd_remove,
};
module_platform_driver(da850_pupd_driver);
MODULE_AUTHOR("David Lechner <david@lechnology.com>");
MODULE_DESCRIPTION("TI DA850/OMAP-L138/AM18XX pullup/pulldown configuration");
MODULE_LICENSE("GPL");
This diff is collapsed.
......@@ -59,6 +59,7 @@
#define GPIO_LS_SYNC 0x60
enum rockchip_pinctrl_type {
RK1108,
RK2928,
RK3066B,
RK3188,
......@@ -624,6 +625,65 @@ static int rockchip_set_mux(struct rockchip_pin_bank *bank, int pin, int mux)
return ret;
}
#define RK1108_PULL_PMU_OFFSET 0x10
#define RK1108_PULL_OFFSET 0x110
#define RK1108_PULL_PINS_PER_REG 8
#define RK1108_PULL_BITS_PER_PIN 2
#define RK1108_PULL_BANK_STRIDE 16
static void rk1108_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank,
int pin_num, struct regmap **regmap,
int *reg, u8 *bit)
{
struct rockchip_pinctrl *info = bank->drvdata;
/* The first 24 pins of the first bank are located in PMU */
if (bank->bank_num == 0) {
*regmap = info->regmap_pmu;
*reg = RK1108_PULL_PMU_OFFSET;
} else {
*reg = RK1108_PULL_OFFSET;
*regmap = info->regmap_base;
/* correct the offset, as we're starting with the 2nd bank */
*reg -= 0x10;
*reg += bank->bank_num * RK1108_PULL_BANK_STRIDE;
}
*reg += ((pin_num / RK1108_PULL_PINS_PER_REG) * 4);
*bit = (pin_num % RK1108_PULL_PINS_PER_REG);
*bit *= RK1108_PULL_BITS_PER_PIN;
}
#define RK1108_DRV_PMU_OFFSET 0x20
#define RK1108_DRV_GRF_OFFSET 0x210
#define RK1108_DRV_BITS_PER_PIN 2
#define RK1108_DRV_PINS_PER_REG 8
#define RK1108_DRV_BANK_STRIDE 16
static void rk1108_calc_drv_reg_and_bit(struct rockchip_pin_bank *bank,
int pin_num, struct regmap **regmap,
int *reg, u8 *bit)
{
struct rockchip_pinctrl *info = bank->drvdata;
/* The first 24 pins of the first bank are located in PMU */
if (bank->bank_num == 0) {
*regmap = info->regmap_pmu;
*reg = RK1108_DRV_PMU_OFFSET;
} else {
*regmap = info->regmap_base;
*reg = RK1108_DRV_GRF_OFFSET;
/* correct the offset, as we're starting with the 2nd bank */
*reg -= 0x10;
*reg += bank->bank_num * RK1108_DRV_BANK_STRIDE;
}
*reg += ((pin_num / RK1108_DRV_PINS_PER_REG) * 4);
*bit = pin_num % RK1108_DRV_PINS_PER_REG;
*bit *= RK1108_DRV_BITS_PER_PIN;
}
#define RK2928_PULL_OFFSET 0x118
#define RK2928_PULL_PINS_PER_REG 16
#define RK2928_PULL_BANK_STRIDE 8
......@@ -1123,6 +1183,7 @@ static int rockchip_get_pull(struct rockchip_pin_bank *bank, int pin_num)
return !(data & BIT(bit))
? PIN_CONFIG_BIAS_PULL_PIN_DEFAULT
: PIN_CONFIG_BIAS_DISABLE;
case RK1108:
case RK3188:
case RK3288:
case RK3368:
......@@ -1169,6 +1230,7 @@ static int rockchip_set_pull(struct rockchip_pin_bank *bank,
spin_unlock_irqrestore(&bank->slock, flags);
break;
case RK1108:
case RK3188:
case RK3288:
case RK3368:
......@@ -1358,6 +1420,7 @@ static bool rockchip_pinconf_pull_valid(struct rockchip_pin_ctrl *ctrl,
pull == PIN_CONFIG_BIAS_DISABLE);
case RK3066B:
return pull ? false : true;
case RK1108:
case RK3188:
case RK3288:
case RK3368:
......@@ -2455,6 +2518,27 @@ static int rockchip_pinctrl_probe(struct platform_device *pdev)
return 0;
}
static struct rockchip_pin_bank rk1108_pin_banks[] = {
PIN_BANK_IOMUX_FLAGS(0, 32, "gpio0", IOMUX_SOURCE_PMU,
IOMUX_SOURCE_PMU,
IOMUX_SOURCE_PMU,
IOMUX_SOURCE_PMU),
PIN_BANK_IOMUX_FLAGS(1, 32, "gpio1", 0, 0, 0, 0),
PIN_BANK_IOMUX_FLAGS(2, 32, "gpio2", 0, 0, 0, 0),
PIN_BANK_IOMUX_FLAGS(3, 32, "gpio3", 0, 0, 0, 0),
};
static struct rockchip_pin_ctrl rk1108_pin_ctrl = {
.pin_banks = rk1108_pin_banks,
.nr_banks = ARRAY_SIZE(rk1108_pin_banks),
.label = "RK1108-GPIO",
.type = RK1108,
.grf_mux_offset = 0x10,
.pmu_mux_offset = 0x0,
.pull_calc_reg = rk1108_calc_pull_reg_and_bit,
.drv_calc_reg = rk1108_calc_drv_reg_and_bit,
};
static struct rockchip_pin_bank rk2928_pin_banks[] = {
PIN_BANK(0, 32, "gpio0"),
PIN_BANK(1, 32, "gpio1"),
......@@ -2684,6 +2768,8 @@ static struct rockchip_pin_ctrl rk3399_pin_ctrl = {
};
static const struct of_device_id rockchip_pinctrl_dt_match[] = {
{ .compatible = "rockchip,rk1108-pinctrl",
.data = (void *)&rk1108_pin_ctrl },
{ .compatible = "rockchip,rk2928-pinctrl",
.data = (void *)&rk2928_pin_ctrl },
{ .compatible = "rockchip,rk3036-pinctrl",
......
This diff is collapsed.
......@@ -1006,7 +1006,7 @@ static void st_pinconf_dbg_show(struct pinctrl_dev *pctldev,
function = st_pctl_get_pin_function(pc, offset);
if (function)
snprintf(f, 10, "Alt Fn %d", function);
snprintf(f, 10, "Alt Fn %u", function);
else
snprintf(f, 5, "GPIO");
......@@ -1181,7 +1181,7 @@ static int st_pctl_dt_parse_groups(struct device_node *np,
if (!strcmp(pp->name, "name"))
continue;
if (pp && (pp->length/sizeof(__be32)) >= OF_GPIO_ARGS_MIN) {
if (pp->length / sizeof(__be32) >= OF_GPIO_ARGS_MIN) {
npins++;
} else {
pr_warn("Invalid st,pins in %s node\n", np->name);
......
This diff is collapsed.
......@@ -247,6 +247,8 @@ static const unsigned int smc0_nor_addr25_pins[] = {1};
static const unsigned int smc0_nand_pins[] = {0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,
12, 13, 14, 16, 17, 18, 19, 20,
21, 22, 23};
static const unsigned int smc0_nand8_pins[] = {0, 2, 3, 4, 5, 6, 7,
8, 9, 10, 11, 12, 13, 14};
/* Note: CAN MIO clock inputs are modeled in the clock framework */
static const unsigned int can0_0_pins[] = {10, 11};
static const unsigned int can0_1_pins[] = {14, 15};
......@@ -445,6 +447,7 @@ static const struct zynq_pctrl_group zynq_pctrl_groups[] = {
DEFINE_ZYNQ_PINCTRL_GRP(smc0_nor_cs1),
DEFINE_ZYNQ_PINCTRL_GRP(smc0_nor_addr25),
DEFINE_ZYNQ_PINCTRL_GRP(smc0_nand),
DEFINE_ZYNQ_PINCTRL_GRP(smc0_nand8),
DEFINE_ZYNQ_PINCTRL_GRP(can0_0),
DEFINE_ZYNQ_PINCTRL_GRP(can0_1),
DEFINE_ZYNQ_PINCTRL_GRP(can0_2),
......@@ -709,7 +712,8 @@ static const char * const sdio1_wp_groups[] = {"gpio0_0_grp",
static const char * const smc0_nor_groups[] = {"smc0_nor_grp"};
static const char * const smc0_nor_cs1_groups[] = {"smc0_nor_cs1_grp"};
static const char * const smc0_nor_addr25_groups[] = {"smc0_nor_addr25_grp"};
static const char * const smc0_nand_groups[] = {"smc0_nand_grp"};
static const char * const smc0_nand_groups[] = {"smc0_nand_grp",
"smc0_nand8_grp"};
static const char * const can0_groups[] = {"can0_0_grp", "can0_1_grp",
"can0_2_grp", "can0_3_grp", "can0_4_grp", "can0_5_grp",
"can0_6_grp", "can0_7_grp", "can0_8_grp", "can0_9_grp",
......
......@@ -79,6 +79,15 @@ config PINCTRL_MSM8916
This is the pinctrl, pinmux, pinconf and gpiolib driver for the
Qualcomm TLMM block found on the Qualcomm 8916 platform.
config PINCTRL_MSM8994
tristate "Qualcomm 8994 pin controller driver"
depends on GPIOLIB && OF
select PINCTRL_MSM
help
This is the pinctrl, pinmux, pinconf and gpiolib driver for the
Qualcomm TLMM block found in the Qualcomm 8994 platform. The
Qualcomm 8992 platform is also supported by this driver.
config PINCTRL_MSM8996
tristate "Qualcomm MSM8996 pin controller driver"
depends on GPIOLIB && OF
......
......@@ -8,6 +8,7 @@ obj-$(CONFIG_PINCTRL_MSM8660) += pinctrl-msm8660.o
obj-$(CONFIG_PINCTRL_MSM8960) += pinctrl-msm8960.o
obj-$(CONFIG_PINCTRL_MSM8X74) += pinctrl-msm8x74.o
obj-$(CONFIG_PINCTRL_MSM8916) += pinctrl-msm8916.o
obj-$(CONFIG_PINCTRL_MSM8994) += pinctrl-msm8994.o
obj-$(CONFIG_PINCTRL_MSM8996) += pinctrl-msm8996.o
obj-$(CONFIG_PINCTRL_QDF2XXX) += pinctrl-qdf2xxx.o
obj-$(CONFIG_PINCTRL_MDM9615) += pinctrl-mdm9615.o
......
This diff is collapsed.
......@@ -61,16 +61,15 @@ static void exynos_irq_mask(struct irq_data *irqd)
struct irq_chip *chip = irq_data_get_irq_chip(irqd);
struct exynos_irq_chip *our_chip = to_exynos_irq_chip(chip);
struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd);
struct samsung_pinctrl_drv_data *d = bank->drvdata;
unsigned long reg_mask = our_chip->eint_mask + bank->eint_offset;
unsigned long mask;
unsigned long flags;
spin_lock_irqsave(&bank->slock, flags);
mask = readl(d->virt_base + reg_mask);
mask = readl(bank->eint_base + reg_mask);
mask |= 1 << irqd->hwirq;
writel(mask, d->virt_base + reg_mask);
writel(mask, bank->eint_base + reg_mask);
spin_unlock_irqrestore(&bank->slock, flags);
}
......@@ -80,10 +79,9 @@ static void exynos_irq_ack(struct irq_data *irqd)
struct irq_chip *chip = irq_data_get_irq_chip(irqd);
struct exynos_irq_chip *our_chip = to_exynos_irq_chip(chip);
struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd);
struct samsung_pinctrl_drv_data *d = bank->drvdata;
unsigned long reg_pend = our_chip->eint_pend + bank->eint_offset;
writel(1 << irqd->hwirq, d->virt_base + reg_pend);
writel(1 << irqd->hwirq, bank->eint_base + reg_pend);
}
static void exynos_irq_unmask(struct irq_data *irqd)
......@@ -91,7 +89,6 @@ static void exynos_irq_unmask(struct irq_data *irqd)
struct irq_chip *chip = irq_data_get_irq_chip(irqd);
struct exynos_irq_chip *our_chip = to_exynos_irq_chip(chip);
struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd);
struct samsung_pinctrl_drv_data *d = bank->drvdata;
unsigned long reg_mask = our_chip->eint_mask + bank->eint_offset;
unsigned long mask;
unsigned long flags;
......@@ -109,9 +106,9 @@ static void exynos_irq_unmask(struct irq_data *irqd)
spin_lock_irqsave(&bank->slock, flags);
mask = readl(d->virt_base + reg_mask);
mask = readl(bank->eint_base + reg_mask);
mask &= ~(1 << irqd->hwirq);
writel(mask, d->virt_base + reg_mask);
writel(mask, bank->eint_base + reg_mask);
spin_unlock_irqrestore(&bank->slock, flags);
}
......@@ -121,7 +118,6 @@ static int exynos_irq_set_type(struct irq_data *irqd, unsigned int type)
struct irq_chip *chip = irq_data_get_irq_chip(irqd);
struct exynos_irq_chip *our_chip = to_exynos_irq_chip(chip);
struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd);
struct samsung_pinctrl_drv_data *d = bank->drvdata;
unsigned int shift = EXYNOS_EINT_CON_LEN * irqd->hwirq;
unsigned int con, trig_type;
unsigned long reg_con = our_chip->eint_con + bank->eint_offset;
......@@ -152,10 +148,10 @@ static int exynos_irq_set_type(struct irq_data *irqd, unsigned int type)
else
irq_set_handler_locked(irqd, handle_level_irq);
con = readl(d->virt_base + reg_con);
con = readl(bank->eint_base + reg_con);
con &= ~(EXYNOS_EINT_CON_MASK << shift);
con |= trig_type << shift;
writel(con, d->virt_base + reg_con);
writel(con, bank->eint_base + reg_con);
return 0;
}
......@@ -166,7 +162,6 @@ static int exynos_irq_request_resources(struct irq_data *irqd)
struct exynos_irq_chip *our_chip = to_exynos_irq_chip(chip);
struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd);
const struct samsung_pin_bank_type *bank_type = bank->type;
struct samsung_pinctrl_drv_data *d = bank->drvdata;
unsigned int shift = EXYNOS_EINT_CON_LEN * irqd->hwirq;
unsigned long reg_con = our_chip->eint_con + bank->eint_offset;
unsigned long flags;
......@@ -188,10 +183,10 @@ static int exynos_irq_request_resources(struct irq_data *irqd)
spin_lock_irqsave(&bank->slock, flags);
con = readl(d->virt_base + reg_con);
con = readl(bank->eint_base + reg_con);
con &= ~(mask << shift);
con |= EXYNOS_EINT_FUNC << shift;
writel(con, d->virt_base + reg_con);
writel(con, bank->eint_base + reg_con);
spin_unlock_irqrestore(&bank->slock, flags);
......@@ -206,7 +201,6 @@ static void exynos_irq_release_resources(struct irq_data *irqd)
struct exynos_irq_chip *our_chip = to_exynos_irq_chip(chip);
struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd);
const struct samsung_pin_bank_type *bank_type = bank->type;
struct samsung_pinctrl_drv_data *d = bank->drvdata;
unsigned int shift = EXYNOS_EINT_CON_LEN * irqd->hwirq;
unsigned long reg_con = our_chip->eint_con + bank->eint_offset;
unsigned long flags;
......@@ -221,10 +215,10 @@ static void exynos_irq_release_resources(struct irq_data *irqd)
spin_lock_irqsave(&bank->slock, flags);
con = readl(d->virt_base + reg_con);
con = readl(bank->eint_base + reg_con);
con &= ~(mask << shift);
con |= FUNC_INPUT << shift;
writel(con, d->virt_base + reg_con);
writel(con, bank->eint_base + reg_con);
spin_unlock_irqrestore(&bank->slock, flags);
......@@ -274,7 +268,7 @@ static irqreturn_t exynos_eint_gpio_irq(int irq, void *data)
struct samsung_pin_bank *bank = d->pin_banks;
unsigned int svc, group, pin, virq;
svc = readl(d->virt_base + EXYNOS_SVC_OFFSET);
svc = readl(bank->eint_base + EXYNOS_SVC_OFFSET);
group = EXYNOS_SVC_GROUP(svc);
pin = svc & EXYNOS_SVC_NUM_MASK;
......@@ -452,7 +446,6 @@ static void exynos_irq_demux_eint16_31(struct irq_desc *desc)
{
struct irq_chip *chip = irq_desc_get_chip(desc);
struct exynos_muxed_weint_data *eintd = irq_desc_get_handler_data(desc);
struct samsung_pinctrl_drv_data *d = eintd->banks[0]->drvdata;
unsigned long pend;
unsigned long mask;
int i;
......@@ -461,9 +454,9 @@ static void exynos_irq_demux_eint16_31(struct irq_desc *desc)
for (i = 0; i < eintd->nr_banks; ++i) {
struct samsung_pin_bank *b = eintd->banks[i];
pend = readl(d->virt_base + b->irq_chip->eint_pend
pend = readl(b->eint_base + b->irq_chip->eint_pend
+ b->eint_offset);
mask = readl(d->virt_base + b->irq_chip->eint_mask
mask = readl(b->eint_base + b->irq_chip->eint_mask
+ b->eint_offset);
exynos_irq_demux_eint(pend & ~mask, b->irq_domain);
}
......@@ -581,7 +574,7 @@ static void exynos_pinctrl_suspend_bank(
struct samsung_pin_bank *bank)
{
struct exynos_eint_gpio_save *save = bank->soc_priv;
void __iomem *regs = drvdata->virt_base;
void __iomem *regs = bank->eint_base;
save->eint_con = readl(regs + EXYNOS_GPIO_ECON_OFFSET
+ bank->eint_offset);
......@@ -610,7 +603,7 @@ static void exynos_pinctrl_resume_bank(
struct samsung_pin_bank *bank)
{
struct exynos_eint_gpio_save *save = bank->soc_priv;
void __iomem *regs = drvdata->virt_base;
void __iomem *regs = bank->eint_base;
pr_debug("%s: con %#010x => %#010x\n", bank->name,
readl(regs + EXYNOS_GPIO_ECON_OFFSET
......@@ -1346,6 +1339,11 @@ static const struct samsung_pin_bank_data exynos5433_pin_banks0[] = {
EXYNOS_PIN_BANK_EINTW(8, 0x020, "gpa1", 0x04),
EXYNOS_PIN_BANK_EINTW(8, 0x040, "gpa2", 0x08),
EXYNOS_PIN_BANK_EINTW(8, 0x060, "gpa3", 0x0c),
EXYNOS_PIN_BANK_EINTW_EXT(8, 0x020, "gpf1", 0x1004, 1),
EXYNOS_PIN_BANK_EINTW_EXT(4, 0x040, "gpf2", 0x1008, 1),
EXYNOS_PIN_BANK_EINTW_EXT(4, 0x060, "gpf3", 0x100c, 1),
EXYNOS_PIN_BANK_EINTW_EXT(8, 0x080, "gpf4", 0x1010, 1),
EXYNOS_PIN_BANK_EINTW_EXT(8, 0x0a0, "gpf5", 0x1014, 1),
};
/* pin banks of exynos5433 pin-controller - AUD */
......@@ -1427,6 +1425,7 @@ const struct samsung_pin_ctrl exynos5433_pin_ctrl[] = {
.eint_wkup_init = exynos_eint_wkup_init,
.suspend = exynos_pinctrl_suspend,
.resume = exynos_pinctrl_resume,
.nr_ext_resources = 1,
}, {
/* pin-controller instance 1 data */
.pin_banks = exynos5433_pin_banks1,
......
......@@ -79,6 +79,17 @@
.name = id \
}
#define EXYNOS_PIN_BANK_EINTW_EXT(pins, reg, id, offs, pctl_idx) \
{ \
.type = &bank_type_alive, \
.pctl_offset = reg, \
.nr_pins = pins, \
.eint_type = EINT_TYPE_WKUP, \
.eint_offset = offs, \
.name = id, \
.pctl_res_idx = pctl_idx, \
} \
/**
* struct exynos_weint_data: irq specific data for all the wakeup interrupts
* generated by the external wakeup interrupt controller.
......
......@@ -151,7 +151,7 @@ static void s3c24xx_eint_set_function(struct samsung_pinctrl_drv_data *d,
u32 val;
/* Make sure that pin is configured as interrupt */
reg = d->virt_base + bank->pctl_offset;
reg = bank->pctl_base + bank->pctl_offset;
shift = pin * bank_type->fld_width[PINCFG_TYPE_FUNC];
mask = (1 << bank_type->fld_width[PINCFG_TYPE_FUNC]) - 1;
......@@ -184,7 +184,7 @@ static int s3c24xx_eint_type(struct irq_data *data, unsigned int type)
s3c24xx_eint_set_handler(data, type);
/* Set up interrupt trigger */
reg = d->virt_base + EINT_REG(index);
reg = bank->eint_base + EINT_REG(index);
shift = EINT_OFFS(index);
val = readl(reg);
......@@ -259,32 +259,29 @@ static void s3c2410_demux_eint0_3(struct irq_desc *desc)
static void s3c2412_eint0_3_ack(struct irq_data *data)
{
struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(data);
struct samsung_pinctrl_drv_data *d = bank->drvdata;
unsigned long bitval = 1UL << data->hwirq;
writel(bitval, d->virt_base + EINTPEND_REG);
writel(bitval, bank->eint_base + EINTPEND_REG);
}
static void s3c2412_eint0_3_mask(struct irq_data *data)
{
struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(data);
struct samsung_pinctrl_drv_data *d = bank->drvdata;
unsigned long mask;
mask = readl(d->virt_base + EINTMASK_REG);
mask = readl(bank->eint_base + EINTMASK_REG);
mask |= (1UL << data->hwirq);
writel(mask, d->virt_base + EINTMASK_REG);
writel(mask, bank->eint_base + EINTMASK_REG);
}
static void s3c2412_eint0_3_unmask(struct irq_data *data)
{
struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(data);
struct samsung_pinctrl_drv_data *d = bank->drvdata;
unsigned long mask;
mask = readl(d->virt_base + EINTMASK_REG);
mask = readl(bank->eint_base + EINTMASK_REG);
mask &= ~(1UL << data->hwirq);
writel(mask, d->virt_base + EINTMASK_REG);
writel(mask, bank->eint_base + EINTMASK_REG);
}
static struct irq_chip s3c2412_eint0_3_chip = {
......@@ -319,34 +316,31 @@ static void s3c2412_demux_eint0_3(struct irq_desc *desc)
static void s3c24xx_eint_ack(struct irq_data *data)
{
struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(data);
struct samsung_pinctrl_drv_data *d = bank->drvdata;
unsigned char index = bank->eint_offset + data->hwirq;
writel(1UL << index, d->virt_base + EINTPEND_REG);
writel(1UL << index, bank->eint_base + EINTPEND_REG);
}
static void s3c24xx_eint_mask(struct irq_data *data)
{
struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(data);
struct samsung_pinctrl_drv_data *d = bank->drvdata;
unsigned char index = bank->eint_offset + data->hwirq;
unsigned long mask;
mask = readl(d->virt_base + EINTMASK_REG);
mask = readl(bank->eint_base + EINTMASK_REG);
mask |= (1UL << index);
writel(mask, d->virt_base + EINTMASK_REG);
writel(mask, bank->eint_base + EINTMASK_REG);
}
static void s3c24xx_eint_unmask(struct irq_data *data)
{
struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(data);
struct samsung_pinctrl_drv_data *d = bank->drvdata;
unsigned char index = bank->eint_offset + data->hwirq;
unsigned long mask;
mask = readl(d->virt_base + EINTMASK_REG);
mask = readl(bank->eint_base + EINTMASK_REG);
mask &= ~(1UL << index);
writel(mask, d->virt_base + EINTMASK_REG);
writel(mask, bank->eint_base + EINTMASK_REG);
}
static struct irq_chip s3c24xx_eint_chip = {
......@@ -362,13 +356,14 @@ static inline void s3c24xx_demux_eint(struct irq_desc *desc,
{
struct s3c24xx_eint_data *data = irq_desc_get_handler_data(desc);
struct irq_chip *chip = irq_desc_get_chip(desc);
struct samsung_pinctrl_drv_data *d = data->drvdata;
struct irq_data *irqd = irq_desc_get_irq_data(desc);
struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd);
unsigned int pend, mask;
chained_irq_enter(chip, desc);
pend = readl(d->virt_base + EINTPEND_REG);
mask = readl(d->virt_base + EINTMASK_REG);
pend = readl(bank->eint_base + EINTPEND_REG);
mask = readl(bank->eint_base + EINTMASK_REG);
pend &= ~mask;
pend &= range;
......
This diff is collapsed.
This diff is collapsed.
......@@ -116,6 +116,7 @@ struct samsung_pin_bank_type {
* struct samsung_pin_bank_data: represent a controller pin-bank (init data).
* @type: type of the bank (register offsets and bitfield widths)
* @pctl_offset: starting offset of the pin-bank registers.
* @pctl_res_idx: index of base address for pin-bank registers.
* @nr_pins: number of pins included in this bank.
* @eint_func: function to set in CON register to configure pin as EINT.
* @eint_type: type of the external interrupt supported by the bank.
......@@ -126,6 +127,7 @@ struct samsung_pin_bank_type {
struct samsung_pin_bank_data {
const struct samsung_pin_bank_type *type;
u32 pctl_offset;
u8 pctl_res_idx;
u8 nr_pins;
u8 eint_func;
enum eint_type eint_type;
......@@ -137,8 +139,10 @@ struct samsung_pin_bank_data {
/**
* struct samsung_pin_bank: represent a controller pin-bank.
* @type: type of the bank (register offsets and bitfield widths)
* @pctl_base: base address of the pin-bank registers
* @pctl_offset: starting offset of the pin-bank registers.
* @nr_pins: number of pins included in this bank.
* @eint_base: base address of the pin-bank EINT registers.
* @eint_func: function to set in CON register to configure pin as EINT.
* @eint_type: type of the external interrupt supported by the bank.
* @eint_mask: bit mask of pins which support EINT function.
......@@ -157,8 +161,10 @@ struct samsung_pin_bank_data {
*/
struct samsung_pin_bank {
const struct samsung_pin_bank_type *type;
void __iomem *pctl_base;
u32 pctl_offset;
u8 nr_pins;
void __iomem *eint_base;
u8 eint_func;
enum eint_type eint_type;
u32 eint_mask;
......@@ -182,6 +188,7 @@ struct samsung_pin_bank {
* struct samsung_pin_ctrl: represent a pin controller.
* @pin_banks: list of pin banks included in this controller.
* @nr_banks: number of pin banks.
* @nr_ext_resources: number of the extra base address for pin banks.
* @eint_gpio_init: platform specific callback to setup the external gpio
* interrupts for the controller.
* @eint_wkup_init: platform specific callback to setup the external wakeup
......@@ -190,6 +197,7 @@ struct samsung_pin_bank {
struct samsung_pin_ctrl {
const struct samsung_pin_bank_data *pin_banks;
u32 nr_banks;
int nr_ext_resources;
int (*eint_gpio_init)(struct samsung_pinctrl_drv_data *);
int (*eint_wkup_init)(struct samsung_pinctrl_drv_data *);
......@@ -200,7 +208,6 @@ struct samsung_pin_ctrl {
/**
* struct samsung_pinctrl_drv_data: wrapper for holding driver data together.
* @node: global list node
* @virt_base: register base address of the controller.
* @dev: device instance representing the controller.
* @irq: interrpt number used by the controller to notify gpio interrupts.
* @ctrl: pin controller instance managed by the driver.
......@@ -215,7 +222,6 @@ struct samsung_pin_ctrl {
*/
struct samsung_pinctrl_drv_data {
struct list_head node;
void __iomem *virt_base;
struct device *dev;
int irq;
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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