pinctrl: samsung: Usability and extensibiltiy improvements
Subsystems (3)
cover pinctrl: samsung: Usability and extensibiltiy improvements
This RFC series is a work on improving usability and extensibiltiy of the pinctrl-samsung driver. It consists of three main parts:
- moving SoC-specific data to device tree
- converting the driver to use one GPIO chip and one IRQ domain per pin bank
- introducing generic wake-up interrupt capability description
What the first part does is replacing static platform-specific data in pinctrl-samsung driver with data dynamically parsed from device tree.
It aims at reducing the SoC-specific part of the driver and thus the amount of modifications to driver sources when adding support for next SoCs (like Exynos4x12).
In addition, it extends the description of SoC-specific attributes to cover all mainlined Samsung SoCs, starting from s3c24xx and ending on latest Exynos5 series, with the exception of 4-bit banks with more than 8 pins on S3C64xx, which will be covered by futher patch(es).
The second part attempts to simplify usage of the driver and fix several problems of current implementation, in particular:
- Simplifies GPIO pin specification in device tree by using pin
namespace local to pin bank instead of local to pin controller, e.g.
gpios = <&gpj0 3 0>;
instead of
gpios = <&pinctrl0 115 0>;- Simplifies GPIO interrupt specification in device tree by using
namespace local to pin bank (and equal to GPIO namespace), e.g.
interrupt-parent = <&gpj0>;
interrupts = <3 0>;
instead of
interrupt-parent = <&pinctrl0>;
interrupts = <115 0>;- Simplifies internal GPIO pin to bank translation thanks to correspondence of particular GPIO chips to pin banks. This allows to remove the (costly in case of GPIO bit-banging drivers) lookup over all banks to find the one that the pin is from.
Third part is focused on removing the static, hard-coded description of wake-up interrupt controller and wake-up interrupt layout.
It defines a (mostly) generic (in scope of targetted SoCs) wake-up interrupt layout specification format that allows to specify which pin banks support wake-up interrupts and how they are handled (direct or multiplexed/chained).
See particular patches for more detailed descriptions and the last patch for updated device tree bindings.
Any comments are welcome.
Tomasz Figa (16):
pinctrl: exynos: Parse wakeup-eint parameters from DT
pinctrl: samsung: Detect and handle unsupported configuration types
pinctrl: samsung: Parse pin banks from DT
pinctrl: exynos: Remove static platform-specific data
pinctrl: samsung: Parse bank-specific eint offset from DT
pinctrl: samsung: Hold OF node of pin bank in bank struct
pinctrl: samsung: Hold pointer to driver data in bank struct
pinctrl: exynos: Use one IRQ domain per pin bank
pinctrl: samsung: Do not pass gpio_chip to pin_to_reg_bank
pinctrl: samsung: Use one GPIO chip per pin bank
pinctrl: samsung: Use per-bank IRQ domain for wake-up interrupts
pinctrl: exynos: Set pin function to EINT in irq_set_type of wake-up
EINT
pinctrl: samsung: Parse offsets of particular registers from DT
ARM: dts: exynos4210: Remove legacy gpio nodes
ARM: dts: exynos4210: Add platform-specific descriptions for pin
controllers
Documentation: Update samsung-pinctrl device tree bindings
documentation
.../bindings/pinctrl/samsung-pinctrl.txt | 212 ++++++++-- arch/arm/boot/dts/exynos4210-pinctrl-banks.dtsi | 459 +++++++++++++++++++++ arch/arm/boot/dts/exynos4210-pinctrl.dtsi | 2 + arch/arm/boot/dts/exynos4210.dtsi | 254 +----------- drivers/pinctrl/pinctrl-exynos.c | 401 ++++++++---------- drivers/pinctrl/pinctrl-exynos.h | 184 +-------- drivers/pinctrl/pinctrl-samsung.c | 372 +++++++++++++---- drivers/pinctrl/pinctrl-samsung.h | 87 ++-- 8 files changed, 1186 insertions(+), 785 deletions(-) create mode 100644 arch/arm/boot/dts/exynos4210-pinctrl-banks.dtsi
Signature · 1 line
1.7.12
RFC PATCH 1/16 pinctrl: exynos: Parse wakeup-eint parameters from DT
This patch converts the pinctrl-exynos driver to parse wakeup interrupt count and register offsets from device tree. It reduces the amount of static platform-specific data and facilitates adding further SoC variants to pinctrl-samsung driver.
--- drivers/pinctrl/pinctrl-exynos.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+)
drivers/pinctrl/pinctrl-exynos.c +22 -0
@@ -435,6 +435,8 @@ static int exynos_eint_wkup_init(struct samsung_pinctrl_drv_data *d)struct device_node *np;struct exynos_weint_data *weint_data;int idx, irq; +u32 val; +int ret;for_each_child_of_node (dev->of_node, np) {if (of_match_node (exynos_wkup_irq_ids, np)) {
@@ -445,6 +447,26 @@ static int exynos_eint_wkup_init(struct samsung_pinctrl_drv_data *d)if (!wkup_np)return -ENODEV ; + ret =of_property_read_u32 (wkup_np,"samsung,weint-count" , &val); +if (ret) +return -EINVAL ; + d->ctrl->nr_wint = val; + + ret =of_property_read_u32 (wkup_np,"samsung,weint-con" , &val); +if (ret) +return -EINVAL ; + d->ctrl->weint_con = val; + + ret =of_property_read_u32 (wkup_np,"samsung,weint-mask" , &val); +if (ret) +return -EINVAL ; + d->ctrl->weint_mask = val; + + ret =of_property_read_u32 (wkup_np,"samsung,weint-pend" , &val); +if (ret) +return -EINVAL ; + d->ctrl->weint_pend = val; + d->wkup_irqd =irq_domain_add_linear (wkup_np, d->ctrl->nr_wint, &exynos_wkup_irqd_ops, d);if (!d->wkup_irqd) {
Signature · 1 line
1.7.12
RFC PATCH 2/16 pinctrl: samsung: Detect and handle unsupported configuration types
In reply to Tomasz Figa--- drivers/pinctrl/pinctrl-samsung.c | 3 +++ 1 file changed, 3 insertions(+)
drivers/pinctrl/pinctrl-samsung.c +3 -0
@@ -391,6 +391,9 @@ static int samsung_pinconf_rw(struct pinctrl_dev *pctldev, unsigned int pin,return -EINVAL ; } +if (!width) +return -EINVAL ; + mask = (1 << width) -1 ; shift = pin_offset * width; data =readl (reg_base + cfg_reg);
Signature · 1 line
1.7.12
RFC PATCH 3/16 pinctrl: samsung: Parse pin banks from DT
In reply to Tomasz FigaCurrently platform-specific properties such as list of pin banks, register offsets and bitfield sizes is being taken from static data structure residing in pinctrl-exynos.c.
This patch modifies the pinctrl-samsung driver to parse all platform-specific data from device tree, which will allow to remove the static data structures and facilitate adding of further SoC variants to the pinctrl-samsung driver.
--- drivers/pinctrl/pinctrl-exynos.c | 5 ++ drivers/pinctrl/pinctrl-samsung.c | 169 +++++++++++++++++++++++++++++++++++++- drivers/pinctrl/pinctrl-samsung.h | 17 +++- 3 files changed, 187 insertions(+), 4 deletions(-)
drivers/pinctrl/pinctrl-exynos.c +5 -0
@@ -599,3 +599,8 @@ struct samsung_pin_ctrl exynos4210_pin_ctrl[] = { .label = "exynos4210-gpio-ctrl2", }, }; + +struct samsung_pin_ctrl_variant exynos4_pin_ctrl = { + .eint_gpio_init = exynos_eint_gpio_init, + .eint_wkup_init = exynos_eint_wkup_init, +};
drivers/pinctrl/pinctrl-samsung.c +167 -2
205 lines not on this page · raw message
drivers/pinctrl/pinctrl-samsung.h +15 -2
@@ -123,7 +123,19 @@ struct samsung_pin_bank {u8 pudpdn_width;enum eint_type eint_type;u32 irq_base; -char *name; +const char *name; +}; + +/** +* struct samsung_pin_ctrl_variant: represents a pin controller variant. +* @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 +* interrupts for the controller. +*/ +struct samsung_pin_ctrl_variant { +int (*eint_gpio_init)(struct samsung_pinctrl_drv_data *); +int (*eint_wkup_init)(struct samsung_pinctrl_drv_data *); };/**
@@ -168,7 +180,7 @@ struct samsung_pin_ctrl {int (*eint_gpio_init)(struct samsung_pinctrl_drv_data *);int (*eint_wkup_init)(struct samsung_pinctrl_drv_data *); -char *label; +const char *label; };/**
@@ -235,5 +247,6 @@ struct samsung_pmx_func {/* list of all exported SoC specific data */ extern struct samsung_pin_ctrl exynos4210_pin_ctrl[]; +extern struct samsung_pin_ctrl_variant exynos4_pin_ctrl;#endif /* __PINCTRL_SAMSUNG_H */
Signature · 1 line
1.7.12
RFC PATCH 4/16 pinctrl: exynos: Remove static platform-specific data
In reply to Tomasz FigaThe patch "pinctrl: samsung: Parse pin banks from DT" introduced parsing platform-specific data from device tree, so there is no need to keep the previously used definitions in headers and source files.
This patch cleans up the pinctrl-exynos driver from unused platform-specific data.
--- drivers/pinctrl/pinctrl-exynos.c | 96 ----------------------- drivers/pinctrl/pinctrl-exynos.h | 157 -------------------------------------- drivers/pinctrl/pinctrl-samsung.h | 1 - 3 files changed, 254 deletions(-)
drivers/pinctrl/pinctrl-exynos.c +0 -96
@@ -504,102 +504,6 @@ static int exynos_eint_wkup_init(struct samsung_pinctrl_drv_data *d)return 0 ; } -/* pin banks of exynos4210 pin-controller 0 */ -static struct samsung_pin_bank exynos4210_pin_banks0[] = { -EXYNOS_PIN_BANK_EINTG (0x000 ,EXYNOS4210_GPIO_A0 ,"gpa0" ), -EXYNOS_PIN_BANK_EINTG (0x020 ,EXYNOS4210_GPIO_A1 ,"gpa1" ), -EXYNOS_PIN_BANK_EINTG (0x040 ,EXYNOS4210_GPIO_B ,"gpb" ), -EXYNOS_PIN_BANK_EINTG (0x060 ,EXYNOS4210_GPIO_C0 ,"gpc0" ), -EXYNOS_PIN_BANK_EINTG (0x080 ,EXYNOS4210_GPIO_C1 ,"gpc1" ), -EXYNOS_PIN_BANK_EINTG (0x0A0 ,EXYNOS4210_GPIO_D0 ,"gpd0" ), -EXYNOS_PIN_BANK_EINTG (0x0C0 ,EXYNOS4210_GPIO_D1 ,"gpd1" ), -EXYNOS_PIN_BANK_EINTG (0x0E0 ,EXYNOS4210_GPIO_E0 ,"gpe0" ), -EXYNOS_PIN_BANK_EINTG (0x100 ,EXYNOS4210_GPIO_E1 ,"gpe1" ), -EXYNOS_PIN_BANK_EINTG (0x120 ,EXYNOS4210_GPIO_E2 ,"gpe2" ), -EXYNOS_PIN_BANK_EINTG (0x140 ,EXYNOS4210_GPIO_E3 ,"gpe3" ), -EXYNOS_PIN_BANK_EINTG (0x160 ,EXYNOS4210_GPIO_E4 ,"gpe4" ), -EXYNOS_PIN_BANK_EINTG (0x180 ,EXYNOS4210_GPIO_F0 ,"gpf0" ), -EXYNOS_PIN_BANK_EINTG (0x1A0 ,EXYNOS4210_GPIO_F1 ,"gpf1" ), -EXYNOS_PIN_BANK_EINTG (0x1C0 ,EXYNOS4210_GPIO_F2 ,"gpf2" ), -EXYNOS_PIN_BANK_EINTG (0x1E0 ,EXYNOS4210_GPIO_F3 ,"gpf3" ), -}; - -/* pin banks of exynos4210 pin-controller 1 */ -static struct samsung_pin_bank exynos4210_pin_banks1[] = { -EXYNOS_PIN_BANK_EINTG (0x000 ,EXYNOS4210_GPIO_J0 ,"gpj0" ), -EXYNOS_PIN_BANK_EINTG (0x020 ,EXYNOS4210_GPIO_J1 ,"gpj1" ), -EXYNOS_PIN_BANK_EINTG (0x040 ,EXYNOS4210_GPIO_K0 ,"gpk0" ), -EXYNOS_PIN_BANK_EINTG (0x060 ,EXYNOS4210_GPIO_K1 ,"gpk1" ), -EXYNOS_PIN_BANK_EINTG (0x080 ,EXYNOS4210_GPIO_K2 ,"gpk2" ), -EXYNOS_PIN_BANK_EINTG (0x0A0 ,EXYNOS4210_GPIO_K3 ,"gpk3" ), -EXYNOS_PIN_BANK_EINTG (0x0C0 ,EXYNOS4210_GPIO_L0 ,"gpl0" ), -EXYNOS_PIN_BANK_EINTG (0x0E0 ,EXYNOS4210_GPIO_L1 ,"gpl1" ), -EXYNOS_PIN_BANK_EINTG (0x100 ,EXYNOS4210_GPIO_L2 ,"gpl2" ), -EXYNOS_PIN_BANK_EINTN (0x120 ,EXYNOS4210_GPIO_Y0 ,"gpy0" ), -EXYNOS_PIN_BANK_EINTN (0x140 ,EXYNOS4210_GPIO_Y1 ,"gpy1" ), -EXYNOS_PIN_BANK_EINTN (0x160 ,EXYNOS4210_GPIO_Y2 ,"gpy2" ), -EXYNOS_PIN_BANK_EINTN (0x180 ,EXYNOS4210_GPIO_Y3 ,"gpy3" ), -EXYNOS_PIN_BANK_EINTN (0x1A0 ,EXYNOS4210_GPIO_Y4 ,"gpy4" ), -EXYNOS_PIN_BANK_EINTN (0x1C0 ,EXYNOS4210_GPIO_Y5 ,"gpy5" ), -EXYNOS_PIN_BANK_EINTN (0x1E0 ,EXYNOS4210_GPIO_Y6 ,"gpy6" ), -EXYNOS_PIN_BANK_EINTN (0xC00 ,EXYNOS4210_GPIO_X0 ,"gpx0" ), -EXYNOS_PIN_BANK_EINTN (0xC20 ,EXYNOS4210_GPIO_X1 ,"gpx1" ), -EXYNOS_PIN_BANK_EINTN (0xC40 ,EXYNOS4210_GPIO_X2 ,"gpx2" ), -EXYNOS_PIN_BANK_EINTN (0xC60 ,EXYNOS4210_GPIO_X3 ,"gpx3" ), -}; - -/* pin banks of exynos4210 pin-controller 2 */ -static struct samsung_pin_bank exynos4210_pin_banks2[] = { -EXYNOS_PIN_BANK_EINTN (0x000 ,EXYNOS4210_GPIO_Z ,"gpz" ), -}; - -/* -* Samsung pinctrl driver data for Exynos4210 SoC. Exynos4210 SoC includes -* three gpio/pin-mux/pinconfig controllers. -*/ -struct samsung_pin_ctrl exynos4210_pin_ctrl[] = { - { -/* pin-controller instance 0 data */ - .pin_banks = exynos4210_pin_banks0, - .nr_banks =ARRAY_SIZE (exynos4210_pin_banks0), - .base =EXYNOS4210_GPIO_A0_START , - .nr_pins =EXYNOS4210_GPIOA_NR_PINS , - .nr_gint =EXYNOS4210_GPIOA_NR_GINT , - .geint_con =EXYNOS_GPIO_ECON_OFFSET , - .geint_mask =EXYNOS_GPIO_EMASK_OFFSET , - .geint_pend =EXYNOS_GPIO_EPEND_OFFSET , - .svc =EXYNOS_SVC_OFFSET , - .eint_gpio_init = exynos_eint_gpio_init, - .label ="exynos4210-gpio-ctrl0" , - }, { -/* pin-controller instance 1 data */ - .pin_banks = exynos4210_pin_banks1, - .nr_banks =ARRAY_SIZE (exynos4210_pin_banks1), - .base =EXYNOS4210_GPIOA_NR_PINS , - .nr_pins =EXYNOS4210_GPIOB_NR_PINS , - .nr_gint =EXYNOS4210_GPIOB_NR_GINT , - .nr_wint =32 , - .geint_con =EXYNOS_GPIO_ECON_OFFSET , - .geint_mask =EXYNOS_GPIO_EMASK_OFFSET , - .geint_pend =EXYNOS_GPIO_EPEND_OFFSET , - .weint_con =EXYNOS_WKUP_ECON_OFFSET , - .weint_mask =EXYNOS_WKUP_EMASK_OFFSET , - .weint_pend =EXYNOS_WKUP_EPEND_OFFSET , - .svc =EXYNOS_SVC_OFFSET , - .eint_gpio_init = exynos_eint_gpio_init, - .eint_wkup_init = exynos_eint_wkup_init, - .label ="exynos4210-gpio-ctrl1" , - }, { -/* pin-controller instance 2 data */ - .pin_banks = exynos4210_pin_banks2, - .nr_banks =ARRAY_SIZE (exynos4210_pin_banks2), - .base =EXYNOS4210_GPIOA_NR_PINS + -EXYNOS4210_GPIOB_NR_PINS , - .nr_pins =EXYNOS4210_GPIOC_NR_PINS , - .label ="exynos4210-gpio-ctrl2" , - }, -}; -struct samsung_pin_ctrl_variant exynos4_pin_ctrl = { .eint_gpio_init = exynos_eint_gpio_init, .eint_wkup_init = exynos_eint_wkup_init,
drivers/pinctrl/pinctrl-exynos.h +0 -157
169 lines not on this page · raw message
drivers/pinctrl/pinctrl-samsung.h +0 -1
@@ -246,7 +246,6 @@ struct samsung_pmx_func { };/* list of all exported SoC specific data */ -extern struct samsung_pin_ctrl exynos4210_pin_ctrl[];extern struct samsung_pin_ctrl_variant exynos4_pin_ctrl;#endif /* __PINCTRL_SAMSUNG_H */
Signature · 1 line
1.7.12
RFC PATCH 5/16 pinctrl: samsung: Parse bank-specific eint offset from DT
In reply to Tomasz FigaSome SoCs, like Exynos4x12, have non-linear layout of EINT control registers and so current way of calculating register addresses does not work correctly for them.
This patch adds parsing of samsung,eint-offset property from bank nodes and uses the read values instead of calculating the offsets from bank index.
--- drivers/pinctrl/pinctrl-exynos.c | 5 ++--- drivers/pinctrl/pinctrl-samsung.c | 5 +++++ drivers/pinctrl/pinctrl-samsung.h | 1 + 3 files changed, 8 insertions(+), 3 deletions(-)
drivers/pinctrl/pinctrl-exynos.c +2 -3
@@ -146,7 +146,7 @@ static struct exynos_geint_data *exynos_get_eint_data(irq_hw_number_t hw,struct samsung_pin_bank *bank = d->ctrl->pin_banks;struct exynos_geint_data *eint_data;unsigned int nr_banks = d->ctrl->nr_banks, idx; -unsigned int irq_base =0 , eint_offset =0 ; +unsigned int irq_base =0 ;if (hw >= d->ctrl->nr_gint) {dev_err (d->dev,"unsupported ext-gpio interrupt\n" );
@@ -159,7 +159,6 @@ static struct exynos_geint_data *exynos_get_eint_data(irq_hw_number_t hw,if ((hw >= irq_base) && (hw < (irq_base + bank->nr_pins)))break ; irq_base += bank->nr_pins; - eint_offset +=4 ; }if (idx == nr_banks) {
@@ -175,7 +174,7 @@ static struct exynos_geint_data *exynos_get_eint_data(irq_hw_number_t hw, eint_data->bank = bank; eint_data->pin = hw - irq_base; - eint_data->eint_offset = eint_offset; + eint_data->eint_offset = bank->eint_offset;return eint_data; }
drivers/pinctrl/pinctrl-samsung.c +5 -0
@@ -859,6 +859,11 @@ static int samsung_pinctrl_parse_dt_bank(struct samsung_pin_bank *bank, bank->eint_type =EINT_TYPE_GPIO ; + ret =of_property_read_u32 (np,"samsung,eint-offset" , &val); +if (ret) +return ret; + bank->eint_offset = val; +return 0 ; }
drivers/pinctrl/pinctrl-samsung.h +1 -0
@@ -122,6 +122,7 @@ struct samsung_pin_bank {u8 conpdn_width;u8 pudpdn_width;enum eint_type eint_type; +u32 eint_offset;u32 irq_base;const char *name; };
Signature · 1 line
1.7.12
RFC PATCH 6/16 pinctrl: samsung: Hold OF node of pin bank in bank struct
In reply to Tomasz FigaThe node pointer will be used in extensions added by patches that will follow.
--- drivers/pinctrl/pinctrl-samsung.c | 1 + drivers/pinctrl/pinctrl-samsung.h | 3 +++ 2 files changed, 4 insertions(+)
drivers/pinctrl/pinctrl-samsung.c +1 -0
@@ -850,6 +850,7 @@ static int samsung_pinctrl_parse_dt_bank(struct samsung_pin_bank *bank,return ret; bank->nr_pins = val; + bank->of_node = np; bank->name = np->name;if (!of_find_property (np,"interrupt-controller" ,NULL )) {
drivers/pinctrl/pinctrl-samsung.h +3 -0
@@ -111,6 +111,7 @@ struct samsung_pinctrl_drv_data;* @eint_type: type of the external interrupt supported by the bank. * @irq_base: starting controller local irq number of the bank. * @name: name to be prefixed for each pin in this pin bank. +* @of_node: node of pin bank in device tree */ struct samsung_pin_bank {u32 pctl_offset;
@@ -125,6 +126,8 @@ struct samsung_pin_bank {u32 eint_offset;u32 irq_base;const char *name; + +struct device_node *of_node; };/**
Signature · 1 line
1.7.12
RFC PATCH 7/16 pinctrl: samsung: Hold pointer to driver data in bank struct
In reply to Tomasz FigaThe pointer will be used by further extensions added to the driver.
--- drivers/pinctrl/pinctrl-samsung.c | 20 +++++++++++--------- drivers/pinctrl/pinctrl-samsung.h | 2 ++ 2 files changed, 13 insertions(+), 9 deletions(-)
drivers/pinctrl/pinctrl-samsung.c +11 -9
@@ -870,11 +870,12 @@ static int samsung_pinctrl_parse_dt_bank(struct samsung_pin_bank *bank,/* retrieve the soc specific data */ static struct samsung_pin_ctrl *samsung_pinctrl_get_soc_data ( -struct platform_device *pdev) +struct platform_device *pdev, +struct samsung_pinctrl_drv_data *d) {int id;const struct of_device_id *match; -const struct device_node *node = pdev->dev.of_node; +struct device_node *node = pdev->dev.of_node;struct device_node *bank_np;struct samsung_pin_ctrl *ctrl;struct samsung_pin_bank *banks, *b;
@@ -884,7 +885,7 @@ static struct samsung_pin_ctrl *samsung_pinctrl_get_soc_data(u32 val;int ret; - id =of_alias_get_id (pdev->dev.of_node,"pinctrl" ); + id =of_alias_get_id (node,"pinctrl" );if (id <0 ) {dev_err (&pdev->dev,"failed to get alias id\n" );return NULL ;
@@ -922,6 +923,7 @@ static struct samsung_pin_ctrl *samsung_pinctrl_get_soc_data(continue ;if (samsung_pinctrl_parse_dt_bank (b, bank_np))return NULL ; + b->drvdata = d; b->pin_base = ctrl->nr_pins; ctrl->nr_pins += b->nr_pins;if (b->eint_type ==EINT_TYPE_GPIO ) {
@@ -979,18 +981,18 @@ static int __devinit samsung_pinctrl_probe(struct platform_device *pdev)return -ENODEV ; } - ctrl =samsung_pinctrl_get_soc_data (pdev); -if (!ctrl) { -dev_err (&pdev->dev,"driver data not available\n" ); -return -EINVAL ; - } - drvdata =devm_kzalloc (dev,sizeof (*drvdata),GFP_KERNEL );if (!drvdata) {dev_err (dev,"failed to allocate memory for driver's " "private data\n" );return -ENOMEM ; } + + ctrl =samsung_pinctrl_get_soc_data (pdev, drvdata); +if (!ctrl) { +dev_err (&pdev->dev,"driver data not available\n" ); +return -EINVAL ; + } drvdata->ctrl = ctrl; drvdata->dev = dev;
drivers/pinctrl/pinctrl-samsung.h +2 -0
@@ -112,6 +112,7 @@ struct samsung_pinctrl_drv_data;* @irq_base: starting controller local irq number of the bank. * @name: name to be prefixed for each pin in this pin bank. * @of_node: node of pin bank in device tree +* @drvdata: link to controller driver data */ struct samsung_pin_bank {u32 pctl_offset;
@@ -128,6 +129,7 @@ struct samsung_pin_bank {const char *name;struct device_node *of_node; +struct samsung_pinctrl_drv_data *drvdata; };/**
Signature · 1 line
1.7.12
RFC PATCH 8/16 pinctrl: exynos: Use one IRQ domain per pin bank
In reply to Tomasz FigaInstead of registering one IRQ domain for all pin banks of a pin controller, this patch implements registration of per-bank domains.
At a cost of a little memory overhead (~2.5KiB for all GPIO interrupts of Exynos4x12) it simplifies driver code and device tree sources, because GPIO interrupts can be now specified per banks.
Example:
device {
/* ... */
interrupt-parent = <&gpa1>;
interrupts = <3 0>;
/* ... */
};--- drivers/pinctrl/pinctrl-exynos.c | 117 +++++++++++--------------------------- drivers/pinctrl/pinctrl-exynos.h | 12 ---- drivers/pinctrl/pinctrl-samsung.c | 5 +- drivers/pinctrl/pinctrl-samsung.h | 7 +-- 4 files changed, 36 insertions(+), 105 deletions(-)
drivers/pinctrl/pinctrl-exynos.c +33 -84
@@ -40,46 +40,46 @@ static const struct of_device_id exynos_wkup_irq_ids[] = {static void exynos_gpio_irq_unmask (struct irq_data *irqd) { -struct samsung_pinctrl_drv_data *d = irqd->domain->host_data; -struct exynos_geint_data *edata =irq_data_get_irq_handler_data (irqd); -unsigned long reg_mask = d->ctrl->geint_mask + edata->eint_offset; +struct samsung_pin_bank *bank =irq_data_get_irq_chip_data (irqd); +struct samsung_pinctrl_drv_data *d = bank->drvdata; +unsigned long reg_mask = d->ctrl->geint_mask + bank->eint_offset;unsigned long mask; mask =readl (d->virt_base + reg_mask); - mask &= ~(1 << edata->pin); + mask &= ~(1 << irqd->hwirq);writel (mask, d->virt_base + reg_mask); }static void exynos_gpio_irq_mask (struct irq_data *irqd) { -struct samsung_pinctrl_drv_data *d = irqd->domain->host_data; -struct exynos_geint_data *edata =irq_data_get_irq_handler_data (irqd); -unsigned long reg_mask = d->ctrl->geint_mask + edata->eint_offset; +struct samsung_pin_bank *bank =irq_data_get_irq_chip_data (irqd); +struct samsung_pinctrl_drv_data *d = bank->drvdata; +unsigned long reg_mask = d->ctrl->geint_mask + bank->eint_offset;unsigned long mask; mask =readl (d->virt_base + reg_mask); - mask |=1 << edata->pin; + mask |=1 << irqd->hwirq;writel (mask, d->virt_base + reg_mask); }static void exynos_gpio_irq_ack (struct irq_data *irqd) { -struct samsung_pinctrl_drv_data *d = irqd->domain->host_data; -struct exynos_geint_data *edata =irq_data_get_irq_handler_data (irqd); -unsigned long reg_pend = d->ctrl->geint_pend + edata->eint_offset; +struct samsung_pin_bank *bank =irq_data_get_irq_chip_data (irqd); +struct samsung_pinctrl_drv_data *d = bank->drvdata; +unsigned long reg_pend = d->ctrl->geint_pend + bank->eint_offset; -writel (1 << edata->pin, d->virt_base + reg_pend); +writel (1 << irqd->hwirq, d->virt_base + reg_pend); }static int exynos_gpio_irq_set_type (struct irq_data *irqd,unsigned int type) { -struct samsung_pinctrl_drv_data *d = irqd->domain->host_data; +struct samsung_pin_bank *bank =irq_data_get_irq_chip_data (irqd); +struct samsung_pinctrl_drv_data *d = bank->drvdata;struct samsung_pin_ctrl *ctrl = d->ctrl; -struct exynos_geint_data *edata =irq_data_get_irq_handler_data (irqd); -struct samsung_pin_bank *bank = edata->bank; -unsigned int shift =EXYNOS_EINT_CON_LEN * edata->pin; +unsigned int pin = irqd->hwirq; +unsigned int shift =EXYNOS_EINT_CON_LEN * pin;unsigned int con, trig_type; -unsigned long reg_con = ctrl->geint_con + edata->eint_offset; +unsigned long reg_con = ctrl->geint_con + bank->eint_offset;unsigned int mask;switch (type) {
@@ -114,7 +114,7 @@ static int exynos_gpio_irq_set_type(struct irq_data *irqd, unsigned int type)writel (con, d->virt_base + reg_con); reg_con = bank->pctl_offset; - shift = edata->pin * bank->func_width; + shift = pin * bank->func_width; mask = (1 << bank->func_width) -1 ; con =readl (d->virt_base + reg_con);
@@ -136,81 +136,23 @@ static struct irq_chip exynos_gpio_irq_chip = { .irq_set_type = exynos_gpio_irq_set_type, }; -/* -* given a controller-local external gpio interrupt number, prepare the handler -* data for it. -*/ -static struct exynos_geint_data *exynos_get_eint_data (irq_hw_number_t hw, -struct samsung_pinctrl_drv_data *d) -{ -struct samsung_pin_bank *bank = d->ctrl->pin_banks; -struct exynos_geint_data *eint_data; -unsigned int nr_banks = d->ctrl->nr_banks, idx; -unsigned int irq_base =0 ; - -if (hw >= d->ctrl->nr_gint) { -dev_err (d->dev,"unsupported ext-gpio interrupt\n" ); -return NULL ; - } - -for (idx =0 ; idx < nr_banks; idx++, bank++) { -if (bank->eint_type !=EINT_TYPE_GPIO ) -continue ; -if ((hw >= irq_base) && (hw < (irq_base + bank->nr_pins))) -break ; - irq_base += bank->nr_pins; - } - -if (idx == nr_banks) { -dev_err (d->dev,"pin bank not found for ext-gpio interrupt\n" ); -return NULL ; - } - - eint_data =devm_kzalloc (d->dev,sizeof (*eint_data),GFP_KERNEL ); -if (!eint_data) { -dev_err (d->dev,"no memory for eint-gpio data\n" ); -return NULL ; - } - - eint_data->bank = bank; - eint_data->pin = hw - irq_base; - eint_data->eint_offset = bank->eint_offset; -return eint_data; -} -static int exynos_gpio_irq_map (struct irq_domain *h,unsigned int virq,irq_hw_number_t hw) { -struct samsung_pinctrl_drv_data *d = h->host_data; -struct exynos_geint_data *eint_data; - - eint_data =exynos_get_eint_data (hw, d); -if (!eint_data) -return -EINVAL ; +struct samsung_pin_bank *b = h->host_data; -irq_set_handler_data (virq, eint_data); -irq_set_chip_data (virq, h->host_data); +irq_set_chip_data (virq, b);irq_set_chip_and_handler (virq, &exynos_gpio_irq_chip, handle_level_irq);set_irq_flags (virq,IRQF_VALID );return 0 ; } -static void exynos_gpio_irq_unmap (struct irq_domain *h,unsigned int virq) -{ -struct samsung_pinctrl_drv_data *d = h->host_data; -struct exynos_geint_data *eint_data; - - eint_data =irq_get_handler_data (virq); -devm_kfree (d->dev, eint_data); -} -/* * irq domain callbacks for external gpio interrupt controller. */ static const struct irq_domain_ops exynos_gpio_irqd_ops = { .map = exynos_gpio_irq_map, - .unmap = exynos_gpio_irq_unmap, .xlate = irq_domain_xlate_twocell, };
@@ -229,7 +171,7 @@ static irqreturn_t exynos_eint_gpio_irq(int irq, void *data)return IRQ_HANDLED ; bank += (group -1 ); - virq =irq_linear_revmap (d->gpio_irqd, bank->irq_base + pin); + virq =irq_linear_revmap (bank->irq_domain, pin);if (!virq)return IRQ_NONE ;generic_handle_irq (virq);
@@ -242,8 +184,10 @@ static irqreturn_t exynos_eint_gpio_irq(int irq, void *data)*/ static int exynos_eint_gpio_init (struct samsung_pinctrl_drv_data *d) { +struct samsung_pin_bank *bank;struct device *dev = d->dev;unsigned int ret; +unsigned int i;if (!d->irq) {dev_err (dev,"irq number not available\n" );
@@ -257,11 +201,16 @@ static int exynos_eint_gpio_init(struct samsung_pinctrl_drv_data *d)return -ENXIO ; } - d->gpio_irqd =irq_domain_add_linear (dev->of_node, d->ctrl->nr_gint, - &exynos_gpio_irqd_ops, d); -if (!d->gpio_irqd) { -dev_err (dev,"gpio irq domain allocation failed\n" ); -return -ENXIO ; + bank = d->ctrl->pin_banks; +for (i =0 ; i < d->ctrl->nr_banks; ++i, ++bank) { +if (bank->eint_type !=EINT_TYPE_GPIO ) +continue ; + bank->irq_domain =irq_domain_add_linear (bank->of_node, + bank->nr_pins, &exynos_gpio_irqd_ops, bank); +if (!bank->irq_domain) { +dev_err (dev,"gpio irq domain add failed\n" ); +return -ENXIO ; + } }return 0 ;
drivers/pinctrl/pinctrl-exynos.h +0 -12
@@ -38,18 +38,6 @@#define EXYNOS_EINT_MAX_PER_BANK 8/** -* struct exynos_geint_data: gpio eint specific data for irq_chip callbacks. -* @bank: pin bank from which this gpio interrupt originates. -* @pin: pin number within the bank. -* @eint_offset: offset to be added to the con/pend/mask register bank base. -*/ -struct exynos_geint_data { -struct samsung_pin_bank *bank; -u32 pin; -u32 eint_offset; -}; - -/** * struct exynos_weint_data: irq specific data for all the wakeup interrupts * generated by the external wakeup interrupt controller. * @domain: irq domain representing the external wakeup interrupts
drivers/pinctrl/pinctrl-samsung.c +1 -4
@@ -926,10 +926,8 @@ static struct samsung_pin_ctrl *samsung_pinctrl_get_soc_data( b->drvdata = d; b->pin_base = ctrl->nr_pins; ctrl->nr_pins += b->nr_pins; -if (b->eint_type ==EINT_TYPE_GPIO ) { - b->irq_base = eint_cnt; +if (b->eint_type ==EINT_TYPE_GPIO ) eint_cnt += b->nr_pins; - } ++b; }
@@ -959,7 +957,6 @@ static struct samsung_pin_ctrl *samsung_pinctrl_get_soc_data( ctrl->pin_banks = banks; ctrl->nr_banks = bank_cnt; - ctrl->nr_gint = eint_cnt; ctrl->label = node->name; ctrl->eint_wkup_init = variant->eint_wkup_init; ctrl->base = pin_base;
drivers/pinctrl/pinctrl-samsung.h +2 -5
@@ -109,10 +109,10 @@ struct samsung_pinctrl_drv_data;* @conpdn_width: width of the sleep mode function selector bin field. * @pudpdn_width: width of the sleep mode pull up/down selector bit field. * @eint_type: type of the external interrupt supported by the bank. -* @irq_base: starting controller local irq number of the bank. * @name: name to be prefixed for each pin in this pin bank. * @of_node: node of pin bank in device tree * @drvdata: link to controller driver data +* @irq_domain: IRQ domain of the bank. */ struct samsung_pin_bank {u32 pctl_offset;
@@ -125,11 +125,11 @@ struct samsung_pin_bank {u8 pudpdn_width;enum eint_type eint_type;u32 eint_offset; -u32 irq_base;const char *name;struct device_node *of_node;struct samsung_pinctrl_drv_data *drvdata; +struct irq_domain *irq_domain; };/**
@@ -150,7 +150,6 @@ struct samsung_pin_ctrl_variant {* @nr_banks: number of pin banks. * @base: starting system wide pin number. * @nr_pins: number of pins supported by the controller. -* @nr_gint: number of external gpio interrupts supported. * @nr_wint: number of external wakeup interrupts supported. * @geint_con: offset of the ext-gpio controller registers. * @geint_mask: offset of the ext-gpio interrupt mask registers.
@@ -171,7 +170,6 @@ struct samsung_pin_ctrl {u32 base;u32 nr_pins; -u32 nr_gint;u32 nr_wint;u32 geint_con;
@@ -218,7 +216,6 @@ struct samsung_pinctrl_drv_data {const struct samsung_pmx_func *pmx_functions;unsigned int nr_functions; -struct irq_domain *gpio_irqd;struct irq_domain *wkup_irqd;struct gpio_chip *gc;
Signature · 1 line
1.7.12
RFC PATCH 9/16 pinctrl: samsung: Do not pass gpio_chip to pin_to_reg_bank
In reply to Tomasz FigaThe pointer to gpio_chip passed to pin_to_reg_bank utility function is used only to retrieve a pointer to samsung_pinctrl_drv_data structure.
This patch modifies the function and its users to pass a pointer to samsung_pinctrl_drv_data directly.
--- drivers/pinctrl/pinctrl-samsung.c | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-)
drivers/pinctrl/pinctrl-samsung.c +16 -9
@@ -252,14 +252,12 @@ static int samsung_pinmux_get_groups(struct pinctrl_dev *pctldev,* given a pin number that is local to a pin controller, find out the pin bank * and the register base of the pin bank. */ -static void pin_to_reg_bank (struct gpio_chip *gc,unsigned pin, -void __iomem **reg,u32 *offset, +static void pin_to_reg_bank (struct samsung_pinctrl_drv_data *drvdata, +unsigned pin,void __iomem **reg,u32 *offset,struct samsung_pin_bank **bank) { -struct samsung_pinctrl_drv_data *drvdata;struct samsung_pin_bank *b; - drvdata =dev_get_drvdata (gc->dev); b = drvdata->ctrl->pin_banks; while ((pin >= b->pin_base) &&
@@ -294,7 +292,7 @@ static void samsung_pinmux_setup(struct pinctrl_dev *pctldev, unsigned selector,* pin function number in the config register. */ for (cnt =0 ; cnt < drvdata->pin_groups[group].num_pins; cnt++) { -pin_to_reg_bank (drvdata->gc, pins[cnt] - drvdata->ctrl->base, +pin_to_reg_bank (drvdata, pins[cnt] - drvdata->ctrl->base, ®, &pin_offset, &bank); mask = (1 << bank->func_width) -1 ; shift = pin_offset * bank->func_width;
@@ -331,10 +329,13 @@ static int samsung_pinmux_gpio_set_direction(struct pinctrl_dev *pctldev, struct pinctrl_gpio_range *range, unsigned offset, bool input) { struct samsung_pin_bank *bank; +struct samsung_pinctrl_drv_data *drvdata;void __iomem *reg;u32 data, pin_offset, mask, shift; -pin_to_reg_bank (range->gc, offset, ®, &pin_offset, &bank); + drvdata =pinctrl_dev_get_drvdata (pctldev); + +pin_to_reg_bank (drvdata, offset, ®, &pin_offset, &bank); mask = (1 << bank->func_width) -1 ; shift = pin_offset * bank->func_width;
@@ -368,7 +369,7 @@ static int samsung_pinconf_rw(struct pinctrl_dev *pctldev, unsigned int pin,u32 cfg_value, cfg_reg; drvdata =pinctrl_dev_get_drvdata (pctldev); -pin_to_reg_bank (drvdata->gc, pin - drvdata->ctrl->base, ®_base, +pin_to_reg_bank (drvdata, pin - drvdata->ctrl->base, ®_base, &pin_offset, &bank);switch (cfg_type) {
@@ -470,8 +471,11 @@ static void samsung_gpio_set(struct gpio_chip *gc, unsigned offset, int value) {void __iomem *reg;u32 pin_offset, data; +struct samsung_pinctrl_drv_data *drvdata; -pin_to_reg_bank (gc, offset, ®, &pin_offset,NULL ); + drvdata =dev_get_drvdata (gc->dev); + +pin_to_reg_bank (drvdata, offset, ®, &pin_offset,NULL ); data =readl (reg +DAT_REG ); data &= ~(1 << pin_offset);if (value)
@@ -484,8 +488,11 @@ static int samsung_gpio_get(struct gpio_chip *gc, unsigned offset) {void __iomem *reg;u32 pin_offset, data; +struct samsung_pinctrl_drv_data *drvdata; + + drvdata =dev_get_drvdata (gc->dev); -pin_to_reg_bank (gc, offset, ®, &pin_offset,NULL ); +pin_to_reg_bank (drvdata, offset, ®, &pin_offset,NULL ); data =readl (reg +DAT_REG ); data >>= pin_offset; data &=1 ;
Signature · 1 line
1.7.12
RFC PATCH 10/16 pinctrl: samsung: Use one GPIO chip per pin bank
In reply to Tomasz FigaThis patch modifies the pinctrl-samsung driver to register one GPIO chip per pin bank, instead of a single chip for all pin banks of the controller.
It simplifies GPIO accesses a lot (constant time instead of looping through the list of banks to find the right one) and should have a good effect on performance of any bit-banging driver.
In addition it allows to reference GPIO pins by a phandle to the bank node and a local pin offset inside of the bank (similar to previous gpiolib driver), which is more clear and readable than using indices relative to the whole pin controller.
Example:
device {
/* ... */
gpios = <&gpk0 4 0>;
/* ... */
};--- drivers/pinctrl/pinctrl-samsung.c | 118 +++++++++++++++++++++++--------------- drivers/pinctrl/pinctrl-samsung.h | 12 ++-- 2 files changed, 80 insertions(+), 50 deletions(-)
drivers/pinctrl/pinctrl-samsung.c +73 -45
@@ -48,6 +48,11 @@ struct pin_config {static unsigned int pin_base =0 ; +static inline struct samsung_pin_bank *gc_to_pin_bank (struct gpio_chip *gc) +{ + return container_of(gc, struct samsung_pin_bank, gpio_chip); +} +/* check if the selector is a valid pin group selector */ static int samsung_get_group_count (struct pinctrl_dev *pctldev) {
@@ -333,9 +338,12 @@ static int samsung_pinmux_gpio_set_direction(struct pinctrl_dev *pctldev,void __iomem *reg;u32 data, pin_offset, mask, shift; + bank =gc_to_pin_bank (range->gc); drvdata =pinctrl_dev_get_drvdata (pctldev); -pin_to_reg_bank (drvdata, offset, ®, &pin_offset, &bank); + pin_offset = offset - bank->pin_base; + reg = drvdata->virt_base + bank->pctl_offset; + mask = (1 << bank->func_width) -1 ; shift = pin_offset * bank->func_width;
@@ -469,17 +477,16 @@ static struct pinconf_ops samsung_pinconf_ops = {/* gpiolib gpio_set callback function */ static void samsung_gpio_set (struct gpio_chip *gc,unsigned offset,int value) { +struct samsung_pin_bank *bank =gc_to_pin_bank (gc);void __iomem *reg; -u32 pin_offset, data; -struct samsung_pinctrl_drv_data *drvdata; +u32 data; - drvdata =dev_get_drvdata (gc->dev); + reg = bank->drvdata->virt_base + bank->pctl_offset; -pin_to_reg_bank (drvdata, offset, ®, &pin_offset,NULL ); data =readl (reg +DAT_REG ); - data &= ~(1 << pin_offset); + data &= ~(1 << offset);if (value) - data |=1 << pin_offset; + data |=1 << offset;writel (data, reg +DAT_REG ); }
@@ -487,14 +494,13 @@ static void samsung_gpio_set(struct gpio_chip *gc, unsigned offset, int value)static int samsung_gpio_get (struct gpio_chip *gc,unsigned offset) {void __iomem *reg; -u32 pin_offset, data; -struct samsung_pinctrl_drv_data *drvdata; +u32 data; +struct samsung_pin_bank *bank =gc_to_pin_bank (gc); - drvdata =dev_get_drvdata (gc->dev); + reg = bank->drvdata->virt_base + bank->pctl_offset; -pin_to_reg_bank (drvdata, offset, ®, &pin_offset,NULL ); data =readl (reg +DAT_REG ); - data >>= pin_offset; + data >>= offset; data &=1 ;return data; }
@@ -726,12 +732,15 @@ static int __init samsung_pinctrl_register(struct platform_device *pdev,return -EINVAL ; } - drvdata->grange.name ="samsung-pctrl-gpio-range" ; - drvdata->grange.id =0 ; - drvdata->grange.base = drvdata->ctrl->base; - drvdata->grange.npins = drvdata->ctrl->nr_pins; - drvdata->grange.gc = drvdata->gc; -pinctrl_add_gpio_range (drvdata->pctl_dev, &drvdata->grange); +for (bank =0 ; bank < drvdata->ctrl->nr_banks; ++bank) { + pin_bank = &drvdata->ctrl->pin_banks[bank]; + pin_bank->grange.name = pin_bank->name; + pin_bank->grange.id = bank; + pin_bank->grange.base = pin_bank->gpio_chip.base; + pin_bank->grange.npins = pin_bank->gpio_chip.ngpio; + pin_bank->grange.gc = &pin_bank->gpio_chip; +pinctrl_add_gpio_range (drvdata->pctl_dev, &pin_bank->grange); + } ret =samsung_pinctrl_parse_dt (pdev, drvdata);if (ret) {
@@ -742,49 +751,68 @@ static int __init samsung_pinctrl_register(struct platform_device *pdev,return 0 ; } +static const struct gpio_chip samsung_gpiolib_chip = { + .set = samsung_gpio_set, + .get = samsung_gpio_get, + .direction_input = samsung_gpio_direction_input, + .direction_output = samsung_gpio_direction_output, + .owner =THIS_MODULE , +}; +/* register the gpiolib interface with the gpiolib subsystem */ static int __init samsung_gpiolib_register (struct platform_device *pdev,struct samsung_pinctrl_drv_data *drvdata) { +struct samsung_pin_ctrl *ctrl = drvdata->ctrl; +struct samsung_pin_bank *bank = ctrl->pin_banks;struct gpio_chip *gc;int ret; - - gc =devm_kzalloc (&pdev->dev,sizeof (*gc),GFP_KERNEL ); -if (!gc) { -dev_err (&pdev->dev,"mem alloc for gpio_chip failed\n" ); -return -ENOMEM ; - } - - drvdata->gc = gc; - gc->base = drvdata->ctrl->base; - gc->ngpio = drvdata->ctrl->nr_pins; - gc->dev = &pdev->dev; - gc->set = samsung_gpio_set; - gc->get = samsung_gpio_get; - gc->direction_input = samsung_gpio_direction_input; - gc->direction_output = samsung_gpio_direction_output; - gc->label = drvdata->ctrl->label; - gc->owner =THIS_MODULE ; - ret =gpiochip_add (gc); -if (ret) { -dev_err (&pdev->dev,"failed to register gpio_chip %s, error " -"code: %d\n" , gc->label, ret); -return ret; +int i; + +for (i =0 ; i < ctrl->nr_banks; ++i, ++bank) { + bank->gpio_chip = samsung_gpiolib_chip; + + gc = &bank->gpio_chip; + gc->base = ctrl->base + bank->pin_base; + gc->ngpio = bank->nr_pins; + gc->dev = &pdev->dev; + gc->of_node = bank->of_node; + gc->label = bank->name; + + ret =gpiochip_add (gc); +if (ret) { +dev_err (&pdev->dev,"failed to register gpio_chip %s, error code: %d\n" , + gc->label, ret); + goto fail; + } }return 0 ; + +fail: +for (--i, --bank; i >=0 ; --i, --bank) +if (gpiochip_remove (&bank->gpio_chip)) +dev_err (&pdev->dev,"gpio chip %s remove failed\n" , + bank->gpio_chip.label); +return ret; }/* unregister the gpiolib interface with the gpiolib subsystem */ static int __init samsung_gpiolib_unregister (struct platform_device *pdev,struct samsung_pinctrl_drv_data *drvdata) { -int ret =gpiochip_remove (drvdata->gc); -if (ret) { +struct samsung_pin_ctrl *ctrl = drvdata->ctrl; +struct samsung_pin_bank *bank = ctrl->pin_banks; +int ret =0 ; +int i; + +for (i =0 ; !ret && i < ctrl->nr_banks; ++i, ++bank) + ret =gpiochip_remove (&bank->gpio_chip); + +if (ret)dev_err (&pdev->dev,"gpio chip remove failed\n" ); -return ret; - } -return 0 ; + +return ret; }static const struct of_device_id samsung_pinctrl_dt_match[];
drivers/pinctrl/pinctrl-samsung.h +7 -5
@@ -23,6 +23,8 @@#include <linux/pinctrl/consumer.h> #include <linux/pinctrl/machine.h> +#include <linux/gpio.h> +/* register offsets within a pin bank */ #define DAT_REG 0x4#define PUD_REG 0x8
@@ -113,6 +115,8 @@ struct samsung_pinctrl_drv_data;* @of_node: node of pin bank in device tree * @drvdata: link to controller driver data * @irq_domain: IRQ domain of the bank. +* @gpio_chip: GPIO chip of the bank. +* @grange: linux gpio pin range supported by this bank. */ struct samsung_pin_bank {u32 pctl_offset;
@@ -130,6 +134,9 @@ struct samsung_pin_bank {struct device_node *of_node;struct samsung_pinctrl_drv_data *drvdata;struct irq_domain *irq_domain; + +struct gpio_chip gpio_chip; +struct pinctrl_gpio_range grange; };/**
@@ -199,8 +206,6 @@ struct samsung_pin_ctrl {* @nr_groups: number of such pin groups. * @pmx_functions: list of pin functions available to the driver. * @nr_function: number of such pin functions. -* @gc: gpio_chip instance registered with gpiolib. -* @grange: linux gpio pin range supported by this controller. */ struct samsung_pinctrl_drv_data {void __iomem *virt_base;
@@ -217,9 +222,6 @@ struct samsung_pinctrl_drv_data {unsigned int nr_functions;struct irq_domain *wkup_irqd; - -struct gpio_chip *gc; -struct pinctrl_gpio_range grange; };/**
Signature · 1 line
1.7.12
RFC PATCH 11/16 pinctrl: samsung: Use per-bank IRQ domain for wake-up interrupts
In reply to Tomasz FigaThis patch reworks wake-up interrupt handling in pinctrl-exynos driver, so each pin bank, which provides wake-up interrupts, has its own IRQ domain.
Information about whether given pin bank provides wake-up interrupts, how many and whether they are separate or muxed are parsed from device tree.
It gives following advantages:
- interrupts can be specified in device tree in a more readable way,
e.g. :
device {
/* ... */
interrupt-parent = <&gpx2>;
interrupts = <4 0>;
/* ... */
}; - the amount and layout of interrupts is not hardcoded in the driver anymore
- bank and pin of each wake-up interrupt can be easily identified, to allow operations, such as setting the pin to EINT function, from irq_set_type() callback
--- drivers/pinctrl/pinctrl-exynos.c | 159 +++++++++++++++++++++++--------------- drivers/pinctrl/pinctrl-exynos.h | 17 +++- drivers/pinctrl/pinctrl-samsung.c | 9 ++- drivers/pinctrl/pinctrl-samsung.h | 6 +- 4 files changed, 119 insertions(+), 72 deletions(-)
drivers/pinctrl/pinctrl-exynos.c +97 -62
@@ -218,46 +218,43 @@ static int exynos_eint_gpio_init(struct samsung_pinctrl_drv_data *d)static void exynos_wkup_irq_unmask (struct irq_data *irqd) { -struct samsung_pinctrl_drv_data *d =irq_data_get_irq_chip_data (irqd); -unsigned int bank = irqd->hwirq /EXYNOS_EINT_MAX_PER_BANK ; -unsigned int pin = irqd->hwirq & (EXYNOS_EINT_MAX_PER_BANK -1 ); -unsigned long reg_mask = d->ctrl->weint_mask + (bank <<2 ); +struct samsung_pin_bank *b =irq_data_get_irq_chip_data (irqd); +struct samsung_pinctrl_drv_data *d = b->drvdata; +unsigned long reg_mask = d->ctrl->weint_mask + b->eint_offset;unsigned long mask; mask =readl (d->virt_base + reg_mask); - mask &= ~(1 << pin); + mask &= ~(1 << irqd->hwirq);writel (mask, d->virt_base + reg_mask); }static void exynos_wkup_irq_mask (struct irq_data *irqd) { -struct samsung_pinctrl_drv_data *d =irq_data_get_irq_chip_data (irqd); -unsigned int bank = irqd->hwirq /EXYNOS_EINT_MAX_PER_BANK ; -unsigned int pin = irqd->hwirq & (EXYNOS_EINT_MAX_PER_BANK -1 ); -unsigned long reg_mask = d->ctrl->weint_mask + (bank <<2 ); +struct samsung_pin_bank *b =irq_data_get_irq_chip_data (irqd); +struct samsung_pinctrl_drv_data *d = b->drvdata; +unsigned long reg_mask = d->ctrl->weint_mask + b->eint_offset;unsigned long mask; mask =readl (d->virt_base + reg_mask); - mask |=1 << pin; + mask |=1 << irqd->hwirq;writel (mask, d->virt_base + reg_mask); }static void exynos_wkup_irq_ack (struct irq_data *irqd) { -struct samsung_pinctrl_drv_data *d =irq_data_get_irq_chip_data (irqd); -unsigned int bank = irqd->hwirq /EXYNOS_EINT_MAX_PER_BANK ; -unsigned int pin = irqd->hwirq & (EXYNOS_EINT_MAX_PER_BANK -1 ); -unsigned long pend = d->ctrl->weint_pend + (bank <<2 ); +struct samsung_pin_bank *b =irq_data_get_irq_chip_data (irqd); +struct samsung_pinctrl_drv_data *d = b->drvdata; +unsigned long pend = d->ctrl->weint_pend + b->eint_offset; -writel (1 << pin, d->virt_base + pend); +writel (1 << irqd->hwirq, d->virt_base + pend); }static int exynos_wkup_irq_set_type (struct irq_data *irqd,unsigned int type) { -struct samsung_pinctrl_drv_data *d =irq_data_get_irq_chip_data (irqd); -unsigned int bank = irqd->hwirq /EXYNOS_EINT_MAX_PER_BANK ; -unsigned int pin = irqd->hwirq & (EXYNOS_EINT_MAX_PER_BANK -1 ); -unsigned long reg_con = d->ctrl->weint_con + (bank <<2 ); +struct samsung_pin_bank *bank =irq_data_get_irq_chip_data (irqd); +struct samsung_pinctrl_drv_data *d = bank->drvdata; +unsigned int pin = irqd->hwirq; +unsigned long reg_con = d->ctrl->weint_con + bank->eint_offset;unsigned long shift =EXYNOS_EINT_CON_LEN * pin;unsigned long con, trig_type;
@@ -309,6 +306,7 @@ static struct irq_chip exynos_wkup_irq_chip = {static void exynos_irq_eint0_15 (unsigned int irq,struct irq_desc *desc) {struct exynos_weint_data *eintd =irq_get_handler_data (irq); +struct samsung_pin_bank *bank = eintd->bank;struct irq_chip *chip =irq_get_chip (irq);int eint_irq;
@@ -318,20 +316,20 @@ static void exynos_irq_eint0_15(unsigned int irq, struct irq_desc *desc)if (chip->irq_ack) chip->irq_ack (&desc->irq_data); - eint_irq =irq_linear_revmap (eintd->domain, eintd->irq); + eint_irq =irq_linear_revmap (bank->irq_domain, eintd->irq);generic_handle_irq (eint_irq); chip->irq_unmask (&desc->irq_data);chained_irq_exit (chip, desc); } -static inline void exynos_irq_demux_eint (int irq_base,unsigned long pend, -struct irq_domain *domain) +static inline void exynos_irq_demux_eint (unsigned long pend, +struct irq_domain *domain) {unsigned int irq;while (pend) { irq =fls (pend) -1 ; -generic_handle_irq (irq_find_mapping (domain, irq_base + irq)); +generic_handle_irq (irq_find_mapping (domain, irq)); pend &= ~(1 << irq); } }
@@ -340,18 +338,22 @@ static inline void exynos_irq_demux_eint(int irq_base, unsigned long pend,static void exynos_irq_demux_eint16_31 (unsigned int irq,struct irq_desc *desc) {struct irq_chip *chip =irq_get_chip (irq); -struct exynos_weint_data *eintd =irq_get_handler_data (irq); -struct samsung_pinctrl_drv_data *d = eintd->domain->host_data; +struct exynos_muxed_weint_data *eintd =irq_get_handler_data (irq); +struct samsung_pinctrl_drv_data *d = eintd->banks[0 ]->drvdata; +struct samsung_pin_ctrl *ctrl = d->ctrl;unsigned long pend;unsigned long mask; +int i;chained_irq_enter (chip, desc); - pend =readl (d->virt_base + d->ctrl->weint_pend +0x8 ); - mask =readl (d->virt_base + d->ctrl->weint_mask +0x8 ); -exynos_irq_demux_eint (16 , pend & ~mask, eintd->domain); - pend =readl (d->virt_base + d->ctrl->weint_pend +0xC ); - mask =readl (d->virt_base + d->ctrl->weint_mask +0xC ); -exynos_irq_demux_eint (24 , pend & ~mask, eintd->domain); + +for (i =0 ; i < eintd->nr_banks; ++i) { +struct samsung_pin_bank *b = eintd->banks[i]; + pend =readl (d->virt_base + ctrl->weint_pend + b->eint_offset); + mask =readl (d->virt_base + ctrl->weint_mask + b->eint_offset); +exynos_irq_demux_eint (pend & ~mask, b->irq_domain); + } +chained_irq_exit (chip, desc); }
@@ -381,7 +383,11 @@ static int exynos_eint_wkup_init(struct samsung_pinctrl_drv_data *d)struct device *dev = d->dev;struct device_node *wkup_np =NULL ;struct device_node *np; +struct samsung_pin_bank *bank;struct exynos_weint_data *weint_data; +struct exynos_muxed_weint_data *muxed_data; +unsigned int muxed_banks =0 ; +unsigned int i;int idx, irq;u32 val;int ret;
@@ -395,11 +401,6 @@ static int exynos_eint_wkup_init(struct samsung_pinctrl_drv_data *d)if (!wkup_np)return -ENODEV ; - ret =of_property_read_u32 (wkup_np,"samsung,weint-count" , &val); -if (ret) -return -EINVAL ; - d->ctrl->nr_wint = val; - ret =of_property_read_u32 (wkup_np,"samsung,weint-con" , &val);if (ret)return -EINVAL ;
@@ -415,40 +416,74 @@ static int exynos_eint_wkup_init(struct samsung_pinctrl_drv_data *d)return -EINVAL ; d->ctrl->weint_pend = val; - d->wkup_irqd =irq_domain_add_linear (wkup_np, d->ctrl->nr_wint, - &exynos_wkup_irqd_ops, d); -if (!d->wkup_irqd) { -dev_err (dev,"wakeup irq domain allocation failed\n" ); -return -ENXIO ; + bank = d->ctrl->pin_banks; +for (i =0 ; i < d->ctrl->nr_banks; ++i, ++bank) { +if (bank->eint_type !=EINT_TYPE_WKUP ) +continue ; + + bank->irq_domain =irq_domain_add_linear (bank->of_node, + bank->nr_pins, &exynos_wkup_irqd_ops, bank); +if (!bank->irq_domain) { +dev_err (dev,"wkup irq domain add failed\n" ); +return -ENXIO ; + } + +if (!of_find_property (bank->of_node,"interrupts" ,NULL )) { + bank->eint_type =EINT_TYPE_WKUP_MUX ; + ++muxed_banks; +continue ; + } + + weint_data =devm_kzalloc (dev, bank->nr_pins + *sizeof (*weint_data),GFP_KERNEL ); +if (!weint_data) { +dev_err (dev,"could not allocate memory for weint_data\n" ); +return -ENOMEM ; + } + +for (idx =0 ; idx < bank->nr_pins; ++idx) { + irq =irq_of_parse_and_map (bank->of_node, idx); +if (!irq) { +dev_err (dev,"irq number for eint-%s-%d not found\n" , + bank->name, idx); +continue ; + } + weint_data[idx].irq = idx; + weint_data[idx].bank = bank; +irq_set_handler_data (irq, weint_data); +irq_set_chained_handler (irq, exynos_irq_eint0_15); + } } - weint_data =devm_kzalloc (dev,sizeof (*weint_data) *17 ,GFP_KERNEL ); -if (!weint_data) { -dev_err (dev,"could not allocate memory for weint_data\n" ); -return -ENOMEM ; +if (!muxed_banks) +return 0 ; + + irq =irq_of_parse_and_map (wkup_np,0 ); +if (!irq) { +dev_err (dev,"irq number for muxed EINTs not found\n" ); +return 0 ; } - irq =irq_of_parse_and_map (wkup_np,16 ); -if (irq) { - weint_data[16 ].domain = d->wkup_irqd; -irq_set_chained_handler (irq, exynos_irq_demux_eint16_31); -irq_set_handler_data (irq, &weint_data[16 ]); - }else { -dev_err (dev,"irq number for EINT16-32 not found\n" ); + muxed_data =devm_kzalloc (dev,sizeof (*muxed_data) + + muxed_banks*sizeof (struct samsung_pin_bank *),GFP_KERNEL ); +if (!muxed_data) { +dev_err (dev,"could not allocate memory for muxed_data\n" ); +return -ENOMEM ; } -for (idx =0 ; idx <16 ; idx++) { - weint_data[idx].domain = d->wkup_irqd; - weint_data[idx].irq = idx; +irq_set_chained_handler (irq, exynos_irq_demux_eint16_31); +irq_set_handler_data (irq, muxed_data); - irq =irq_of_parse_and_map (wkup_np, idx); -if (irq) { -irq_set_handler_data (irq, &weint_data[idx]); -irq_set_chained_handler (irq, exynos_irq_eint0_15); - }else { -dev_err (dev,"irq number for eint-%x not found\n" , idx); - } + bank = d->ctrl->pin_banks; + idx =0 ; +for (i =0 ; i < d->ctrl->nr_banks; ++i, ++bank) { +if (bank->eint_type !=EINT_TYPE_WKUP_MUX ) +continue ; + + muxed_data->banks[idx++] = bank; } + muxed_data->nr_banks = muxed_banks; +return 0 ; }
drivers/pinctrl/pinctrl-exynos.h +14 -3
@@ -40,10 +40,21 @@/** * struct exynos_weint_data: irq specific data for all the wakeup interrupts * generated by the external wakeup interrupt controller. -* @domain: irq domain representing the external wakeup interrupts * @irq: interrupt number within the domain. +* @bank: bank responsible for this interrupt */ struct exynos_weint_data { -struct irq_domain *domain; -u32 irq; +unsigned int irq; +struct samsung_pin_bank *bank; +}; + +/** +* struct exynos_muxed_weint_data: irq specific data for muxed wakeup interrupts +* generated by the external wakeup interrupt controller. +* @nr_banks: count of banks being part of the mux +* @banks: array of banks being part of the mux +*/ +struct exynos_muxed_weint_data { +unsigned int nr_banks; +struct samsung_pin_bank *banks[]; };
drivers/pinctrl/pinctrl-samsung.c +6 -3
@@ -615,10 +615,10 @@ static int __init samsung_pinctrl_parse_dt(struct platform_device *pdev,*/ for_each_child_of_node (dev_np, cfg_np) {u32 function; -if (of_find_property (cfg_np,"interrupt-controller" ,NULL )) -continue ;if (of_find_property (cfg_np,"gpio-controller" ,NULL ))continue ; +if (of_find_property (cfg_np,"compatible" ,NULL )) +continue ; ret =samsung_pinctrl_parse_dt_pins (pdev, cfg_np, &drvdata->pctl, &pin_list, &npins);
@@ -893,7 +893,10 @@ static int samsung_pinctrl_parse_dt_bank(struct samsung_pin_bank *bank,return 0 ; } - bank->eint_type =EINT_TYPE_GPIO ; +if (of_find_property (np,"samsung,wkup-eint" ,NULL )) + bank->eint_type =EINT_TYPE_WKUP ; +else + bank->eint_type =EINT_TYPE_GPIO ; ret =of_property_read_u32 (np,"samsung,eint-offset" , &val);if (ret)
drivers/pinctrl/pinctrl-samsung.h +2 -4
@@ -66,6 +66,7 @@ enum pincfg_type {* @EINT_TYPE_NONE: bank does not support external interrupts * @EINT_TYPE_GPIO: bank supportes external gpio interrupts * @EINT_TYPE_WKUP: bank supportes external wakeup interrupts +* @EINT_TYPE_WKUP_MUX: bank supports multiplexed external wakeup interrupts * * Samsung GPIO controller groups all the available pins into banks. The pins * in a pin bank can support external gpio interrupts or external wakeup
@@ -78,6 +79,7 @@ enum eint_type {EINT_TYPE_NONE ,EINT_TYPE_GPIO ,EINT_TYPE_WKUP , + EINT_TYPE_WKUP_MUX, };/* maximum length of a pin in pin descriptor (example: "gpa0-0") */
@@ -157,7 +159,6 @@ struct samsung_pin_ctrl_variant {* @nr_banks: number of pin banks. * @base: starting system wide pin number. * @nr_pins: number of pins supported by the controller. -* @nr_wint: number of external wakeup interrupts supported. * @geint_con: offset of the ext-gpio controller registers. * @geint_mask: offset of the ext-gpio interrupt mask registers. * @geint_pend: offset of the ext-gpio interrupt pending registers.
@@ -177,7 +178,6 @@ struct samsung_pin_ctrl {u32 base;u32 nr_pins; -u32 nr_wint;u32 geint_con;u32 geint_mask;
@@ -220,8 +220,6 @@ struct samsung_pinctrl_drv_data {unsigned int nr_groups;const struct samsung_pmx_func *pmx_functions;unsigned int nr_functions; - -struct irq_domain *wkup_irqd; };/**
Signature · 1 line
1.7.12
RFC PATCH 12/16 pinctrl: exynos: Set pin function to EINT in irq_set_type of wake-up EINT
In reply to Tomasz FigaPins used as wake-up interrupts need to be configured as EINTs. This patch adds the required configuration code to exynos_wkup_irq_set_type, to set the pin as EINT when its interrupt trigger type is configured.
--- drivers/pinctrl/pinctrl-exynos.c | 11 +++++++++++ 1 file changed, 11 insertions(+)
drivers/pinctrl/pinctrl-exynos.c +11 -0
@@ -257,6 +257,7 @@ static int exynos_wkup_irq_set_type(struct irq_data *irqd, unsigned int type)unsigned long reg_con = d->ctrl->weint_con + bank->eint_offset;unsigned long shift =EXYNOS_EINT_CON_LEN * pin;unsigned long con, trig_type; +unsigned int mask;switch (type) {case IRQ_TYPE_EDGE_RISING :
@@ -288,6 +289,16 @@ static int exynos_wkup_irq_set_type(struct irq_data *irqd, unsigned int type) con &= ~(EXYNOS_EINT_CON_MASK << shift); con |= trig_type << shift;writel (con, d->virt_base + reg_con); + + reg_con = bank->pctl_offset; + shift = pin * bank->func_width; + mask = (1 << bank->func_width) -1 ; + + con =readl (d->virt_base + reg_con); + con &= ~(mask << shift); + con |=EXYNOS_EINT_FUNC << shift; +writel (con, d->virt_base + reg_con); +return 0 ; }
Signature · 1 line
1.7.12
RFC PATCH 13/16 pinctrl: samsung: Parse offsets of particular registers from DT
In reply to Tomasz FigaThe order and availability of pin control registers vary with SoC.
This patch modifies the driver to parse register offsets from device tree as a part of bank type definition.
--- drivers/pinctrl/pinctrl-exynos.c | 12 ++--- drivers/pinctrl/pinctrl-samsung.c | 93 +++++++++++++++++++++------------------ drivers/pinctrl/pinctrl-samsung.h | 38 +++++++++------- 3 files changed, 78 insertions(+), 65 deletions(-)
drivers/pinctrl/pinctrl-exynos.c +6 -6
@@ -113,9 +113,9 @@ static int exynos_gpio_irq_set_type(struct irq_data *irqd, unsigned int type) con |= trig_type << shift;writel (con, d->virt_base + reg_con); - reg_con = bank->pctl_offset; - shift = pin * bank->func_width; - mask = (1 << bank->func_width) -1 ; + reg_con = bank->pctl_offset + bank->regs[REG_FUNC ].offset; + shift = pin * bank->regs[REG_FUNC ].width; + mask = (1 << bank->regs[REG_FUNC ].width) -1 ; con =readl (d->virt_base + reg_con); con &= ~(mask << shift);
@@ -290,9 +290,9 @@ static int exynos_wkup_irq_set_type(struct irq_data *irqd, unsigned int type) con |= trig_type << shift;writel (con, d->virt_base + reg_con); - reg_con = bank->pctl_offset; - shift = pin * bank->func_width; - mask = (1 << bank->func_width) -1 ; + reg_con = bank->pctl_offset + bank->regs[REG_FUNC ].offset; + shift = pin * bank->regs[REG_FUNC ].width; + mask = (1 << bank->regs[REG_FUNC ].width) -1 ; con =readl (d->virt_base + reg_con); con &= ~(mask << shift);
drivers/pinctrl/pinctrl-samsung.c +50 -43
158 lines not on this page · raw message
drivers/pinctrl/pinctrl-samsung.h +22 -16
@@ -25,12 +25,16 @@#include <linux/gpio.h> -/* register offsets within a pin bank */ -#define DAT_REG 0x4 -#define PUD_REG 0x8 -#define DRV_REG 0xC -#define CONPDN_REG 0x10 -#define PUDPDN_REG 0x14 +enum pincfg_reg { +REG_FUNC =0 , +REG_DAT , +REG_PUD , +REG_DRV , +REG_CONPDN , +REG_PUDPDN , + +REG_NUM +};/* pinmux function number for pin as gpio output line */ #define FUNC_OUTPUT 0x1
@@ -103,15 +107,21 @@ enum eint_type {struct samsung_pinctrl_drv_data ;/** +* struct samsung_pin_reg: defines a configuration register. +* @offset: offset from bank base. +* @width: with of a bit field used for single pin. +*/ +struct samsung_pin_reg { +u8 offset; +u8 width; +}; + +/** * struct samsung_pin_bank: represent a controller pin-bank. * @reg_offset: starting offset of the pin-bank registers. * @pin_base: starting pin number of the bank. * @nr_pins: number of pins included in this bank. -* @func_width: width of the function selector bit field. -* @pud_width: width of the pin pull up/down selector bit field. -* @drv_width: width of the pin driver strength selector bit field. -* @conpdn_width: width of the sleep mode function selector bin field. -* @pudpdn_width: width of the sleep mode pull up/down selector bit field. +* @regs: low level parameters of available configuration registers. * @eint_type: type of the external interrupt supported by the bank. * @name: name to be prefixed for each pin in this pin bank. * @of_node: node of pin bank in device tree
@@ -124,11 +134,7 @@ struct samsung_pin_bank {u32 pctl_offset;u32 pin_base;u8 nr_pins; -u8 func_width; -u8 pud_width; -u8 drv_width; -u8 conpdn_width; -u8 pudpdn_width; +struct samsung_pin_reg regs[REG_NUM ];enum eint_type eint_type;u32 eint_offset;const char *name;
Signature · 1 line
1.7.12
RFC PATCH 14/16 ARM: dts: exynos4210: Remove legacy gpio nodes
In reply to Tomasz FigaThis patch removes the legacy gpio nodes as the gpio driver is going to be replaced with the new pinctrl driver.
--- arch/arm/boot/dts/exynos4210.dtsi | 229 -------------------------------------- 1 file changed, 229 deletions(-)
arch/arm/boot/dts/exynos4210.dtsi +0 -229
@@ -250,233 +250,4 @@ interrupts = <0 36 0>; }; }; - - gpio-controllers { - #address-cells = <1>; - #size-cells = <1>; - gpio-controller; - ranges; - - gpa0: gpio-controller at 11400000 { - compatible = "samsung,exynos4-gpio"; - reg = <0x11400000 0x20>; - #gpio-cells = <4>; - }; - - gpa1: gpio-controller at 11400020 { - compatible = "samsung,exynos4-gpio"; - reg = <0x11400020 0x20>; - #gpio-cells = <4>; - }; - - gpb: gpio-controller at 11400040 { - compatible = "samsung,exynos4-gpio"; - reg = <0x11400040 0x20>; - #gpio-cells = <4>; - }; - - gpc0: gpio-controller at 11400060 { - compatible = "samsung,exynos4-gpio"; - reg = <0x11400060 0x20>; - #gpio-cells = <4>; - }; - - gpc1: gpio-controller at 11400080 { - compatible = "samsung,exynos4-gpio"; - reg = <0x11400080 0x20>; - #gpio-cells = <4>; - }; - - gpd0: gpio-controller at 114000A0 { - compatible = "samsung,exynos4-gpio"; - reg = <0x114000A0 0x20>; - #gpio-cells = <4>; - }; - - gpd1: gpio-controller at 114000C0 { - compatible = "samsung,exynos4-gpio"; - reg = <0x114000C0 0x20>; - #gpio-cells = <4>; - }; - - gpe0: gpio-controller at 114000E0 { - compatible = "samsung,exynos4-gpio"; - reg = <0x114000E0 0x20>; - #gpio-cells = <4>; - }; - - gpe1: gpio-controller at 11400100 { - compatible = "samsung,exynos4-gpio"; - reg = <0x11400100 0x20>; - #gpio-cells = <4>; - }; - - gpe2: gpio-controller at 11400120 { - compatible = "samsung,exynos4-gpio"; - reg = <0x11400120 0x20>; - #gpio-cells = <4>; - }; - - gpe3: gpio-controller at 11400140 { - compatible = "samsung,exynos4-gpio"; - reg = <0x11400140 0x20>; - #gpio-cells = <4>; - }; - - gpe4: gpio-controller at 11400160 { - compatible = "samsung,exynos4-gpio"; - reg = <0x11400160 0x20>; - #gpio-cells = <4>; - }; - - gpf0: gpio-controller at 11400180 { - compatible = "samsung,exynos4-gpio"; - reg = <0x11400180 0x20>; - #gpio-cells = <4>; - }; - - gpf1: gpio-controller at 114001A0 { - compatible = "samsung,exynos4-gpio"; - reg = <0x114001A0 0x20>; - #gpio-cells = <4>; - }; - - gpf2: gpio-controller at 114001C0 { - compatible = "samsung,exynos4-gpio"; - reg = <0x114001C0 0x20>; - #gpio-cells = <4>; - }; - - gpf3: gpio-controller at 114001E0 { - compatible = "samsung,exynos4-gpio"; - reg = <0x114001E0 0x20>; - #gpio-cells = <4>; - }; - - gpj0: gpio-controller at 11000000 { - compatible = "samsung,exynos4-gpio"; - reg = <0x11000000 0x20>; - #gpio-cells = <4>; - }; - - gpj1: gpio-controller at 11000020 { - compatible = "samsung,exynos4-gpio"; - reg = <0x11000020 0x20>; - #gpio-cells = <4>; - }; - - gpk0: gpio-controller at 11000040 { - compatible = "samsung,exynos4-gpio"; - reg = <0x11000040 0x20>; - #gpio-cells = <4>; - }; - - gpk1: gpio-controller at 11000060 { - compatible = "samsung,exynos4-gpio"; - reg = <0x11000060 0x20>; - #gpio-cells = <4>; - }; - - gpk2: gpio-controller at 11000080 { - compatible = "samsung,exynos4-gpio"; - reg = <0x11000080 0x20>; - #gpio-cells = <4>; - }; - - gpk3: gpio-controller at 110000A0 { - compatible = "samsung,exynos4-gpio"; - reg = <0x110000A0 0x20>; - #gpio-cells = <4>; - }; - - gpl0: gpio-controller at 110000C0 { - compatible = "samsung,exynos4-gpio"; - reg = <0x110000C0 0x20>; - #gpio-cells = <4>; - }; - - gpl1: gpio-controller at 110000E0 { - compatible = "samsung,exynos4-gpio"; - reg = <0x110000E0 0x20>; - #gpio-cells = <4>; - }; - - gpl2: gpio-controller at 11000100 { - compatible = "samsung,exynos4-gpio"; - reg = <0x11000100 0x20>; - #gpio-cells = <4>; - }; - - gpy0: gpio-controller at 11000120 { - compatible = "samsung,exynos4-gpio"; - reg = <0x11000120 0x20>; - #gpio-cells = <4>; - }; - - gpy1: gpio-controller at 11000140 { - compatible = "samsung,exynos4-gpio"; - reg = <0x11000140 0x20>; - #gpio-cells = <4>; - }; - - gpy2: gpio-controller at 11000160 { - compatible = "samsung,exynos4-gpio"; - reg = <0x11000160 0x20>; - #gpio-cells = <4>; - }; - - gpy3: gpio-controller at 11000180 { - compatible = "samsung,exynos4-gpio"; - reg = <0x11000180 0x20>; - #gpio-cells = <4>; - }; - - gpy4: gpio-controller at 110001A0 { - compatible = "samsung,exynos4-gpio"; - reg = <0x110001A0 0x20>; - #gpio-cells = <4>; - }; - - gpy5: gpio-controller at 110001C0 { - compatible = "samsung,exynos4-gpio"; - reg = <0x110001C0 0x20>; - #gpio-cells = <4>; - }; - - gpy6: gpio-controller at 110001E0 { - compatible = "samsung,exynos4-gpio"; - reg = <0x110001E0 0x20>; - #gpio-cells = <4>; - }; - - gpx0: gpio-controller at 11000C00 { - compatible = "samsung,exynos4-gpio"; - reg = <0x11000C00 0x20>; - #gpio-cells = <4>; - }; - - gpx1: gpio-controller at 11000C20 { - compatible = "samsung,exynos4-gpio"; - reg = <0x11000C20 0x20>; - #gpio-cells = <4>; - }; - - gpx2: gpio-controller at 11000C40 { - compatible = "samsung,exynos4-gpio"; - reg = <0x11000C40 0x20>; - #gpio-cells = <4>; - }; - - gpx3: gpio-controller at 11000C60 { - compatible = "samsung,exynos4-gpio"; - reg = <0x11000C60 0x20>; - #gpio-cells = <4>; - }; - - gpz: gpio-controller at 03860000 { - compatible = "samsung,exynos4-gpio"; - reg = <0x03860000 0x20>; - #gpio-cells = <4>; - }; - }; };
Signature · 1 line
1.7.12
RFC PATCH 15/16 ARM: dts: exynos4210: Add platform-specific descriptions for pin controllers
In reply to Tomasz FigaThe patch "pinctrl: samsung: Parse pin banks from DT" introduced platform-specific data parsing from DT.
This patch adds all necessary nodes and properties to exynos4210 device tree sources.
--- arch/arm/boot/dts/exynos4210-pinctrl-banks.dtsi | 459 ++++++++++++++++++++++++ arch/arm/boot/dts/exynos4210-pinctrl.dtsi | 2 + arch/arm/boot/dts/exynos4210.dtsi | 25 +- 3 files changed, 474 insertions(+), 12 deletions(-) create mode 100644 arch/arm/boot/dts/exynos4210-pinctrl-banks.dtsi
arch/arm/boot/dts/exynos4210-pinctrl-banks.dtsi new file +459 -0
@@ -0,0 +1,459 @@ +/* + * Samsung's Exynos4210 SoC pinctrl banks device tree source + * + * Copyright (c) 2012 Samsung Electronics Co., Ltd. + * http://www.samsung.com + * + * Samsung's Exynos4210 SoC pin banks are listed as device tree nodes + * in this file. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +/ { + pinctrl-bank-types { + bank_off: bank-off { + samsung,reg-names = "func", "dat", "pud", + "drv", "conpdn", "pudpdn"; + samsung,reg-params = <0x00 4>, <0x04 1>, <0x08 2>, + <0x0C 2>, <0x10 2>, <0x14 2>; + }; + + bank_alive: bank-alive { + samsung,reg-names = "func", "dat", "pud", + "drv"; + samsung,reg-params = <0x00 4>, <0x04 1>, <0x08 2>, + <0x0C 2>; + }; + }; + + pinctrl at 11400000 { + gpa0: gpa0 { + gpio-controller; + samsung,pctl-offset = <0x000>; + samsung,pin-count = <8>; + samsung,bank-type = <&bank_off>; + #gpio-cells = <2>; + + interrupt-controller; + samsung,eint-offset = <0x00>; + #interrupt-cells = <2>; + }; + + gpa1: gpa1 { + gpio-controller; + samsung,pctl-offset = <0x020>; + samsung,pin-count = <6>; + samsung,bank-type = <&bank_off>; + #gpio-cells = <2>; + + interrupt-controller; + samsung,eint-offset = <0x04>; + #interrupt-cells = <2>; + }; + + gpb: gpb { + gpio-controller; + samsung,pctl-offset = <0x040>; + samsung,pin-count = <8>; + samsung,bank-type = <&bank_off>; + #gpio-cells = <2>; + + interrupt-controller; + samsung,eint-offset = <0x08>; + #interrupt-cells = <2>; + }; + + gpc0: gpc0 { + gpio-controller; + samsung,pctl-offset = <0x060>; + samsung,pin-count = <5>; + samsung,bank-type = <&bank_off>; + #gpio-cells = <2>; + + interrupt-controller; + samsung,eint-offset = <0x0C>; + #interrupt-cells = <2>; + }; + + gpc1: gpc1 { + gpio-controller; + samsung,pctl-offset = <0x080>; + samsung,pin-count = <5>; + samsung,bank-type = <&bank_off>; + #gpio-cells = <2>; + + interrupt-controller; + samsung,eint-offset = <0x10>; + #interrupt-cells = <2>; + }; + + gpd0: gpd0 { + gpio-controller; + samsung,pctl-offset = <0x0A0>; + samsung,pin-count = <4>; + samsung,bank-type = <&bank_off>; + #gpio-cells = <2>; + + interrupt-controller; + samsung,eint-offset = <0x14>; + #interrupt-cells = <2>; + }; + + gpd1: gpd1 { + gpio-controller; + samsung,pctl-offset = <0x0C0>; + samsung,pin-count = <4>; + samsung,bank-type = <&bank_off>; + #gpio-cells = <2>; + + interrupt-controller; + samsung,eint-offset = <0x18>; + #interrupt-cells = <2>; + }; + + gpe0: gpe0 { + gpio-controller; + samsung,pctl-offset = <0x0E0>; + samsung,pin-count = <4>; + samsung,bank-type = <&bank_off>; + #gpio-cells = <2>; + + interrupt-controller; + samsung,eint-offset = <0x1C>; + #interrupt-cells = <2>; + }; + + gpe1: gpe1 { + gpio-controller; + samsung,pctl-offset = <0x100>; + samsung,pin-count = <4>; + samsung,bank-type = <&bank_off>; + #gpio-cells = <2>; + + interrupt-controller; + samsung,eint-offset = <0x20>; + #interrupt-cells = <2>; + }; + + gpe2: gpe2 { + gpio-controller; + samsung,pctl-offset = <0x120>; + samsung,pin-count = <4>; + samsung,bank-type = <&bank_off>; + #gpio-cells = <2>; + + interrupt-controller; + samsung,eint-offset = <0x24>; + #interrupt-cells = <2>; + }; + + gpe3: gpe3 { + gpio-controller; + samsung,pctl-offset = <0x140>; + samsung,pin-count = <4>; + samsung,bank-type = <&bank_off>; + #gpio-cells = <2>; + + interrupt-controller; + samsung,eint-offset = <0x28>; + #interrupt-cells = <2>; + }; + + gpe4: gpe4 { + gpio-controller; + samsung,pctl-offset = <0x160>; + samsung,pin-count = <4>; + samsung,bank-type = <&bank_off>; + #gpio-cells = <2>; + + interrupt-controller; + samsung,eint-offset = <0x2C>; + #interrupt-cells = <2>; + }; + + gpf0: gpf0 { + gpio-controller; + samsung,pctl-offset = <0x180>; + samsung,pin-count = <8>; + samsung,bank-type = <&bank_off>; + #gpio-cells = <2>; + + interrupt-controller; + samsung,eint-offset = <0x30>; + #interrupt-cells = <2>; + }; + + gpf1: gpf1 { + gpio-controller; + samsung,pctl-offset = <0x1A0>; + samsung,pin-count = <8>; + samsung,bank-type = <&bank_off>; + #gpio-cells = <2>; + + interrupt-controller; + samsung,eint-offset = <0x34>; + #interrupt-cells = <2>; + }; + + gpf2: gpf2 { + gpio-controller; + samsung,pctl-offset = <0x1C0>; + samsung,pin-count = <8>; + samsung,bank-type = <&bank_off>; + #gpio-cells = <2>; + + interrupt-controller; + samsung,eint-offset = <0x38>; + #interrupt-cells = <2>; + }; + + gpf3: gpf3 { + gpio-controller; + samsung,pctl-offset = <0x1E0>; + samsung,pin-count = <6>; + samsung,bank-type = <&bank_off>; + #gpio-cells = <2>; + + interrupt-controller; + samsung,eint-offset = <0x3C>; + #interrupt-cells = <2>; + }; + }; + + pinctrl at 11000000 { + gpj0: gpj0 { + gpio-controller; + samsung,pctl-offset = <0x000>; + samsung,pin-count = <8>; + samsung,bank-type = <&bank_off>; + #gpio-cells = <2>; + + interrupt-controller; + samsung,eint-offset = <0x00>; + #interrupt-cells = <2>; + }; + + gpj1: gpj1 { + gpio-controller; + samsung,pctl-offset = <0x020>; + samsung,pin-count = <5>; + samsung,bank-type = <&bank_off>; + #gpio-cells = <2>; + + interrupt-controller; + samsung,eint-offset = <0x04>; + #interrupt-cells = <2>; + }; + + gpk0: gpk0 { + gpio-controller; + samsung,pctl-offset = <0x040>; + samsung,pin-count = <7>; + samsung,bank-type = <&bank_off>; + #gpio-cells = <2>; + + interrupt-controller; + samsung,eint-offset = <0x08>; + #interrupt-cells = <2>; + }; + + gpk1: gpk1 { + gpio-controller; + samsung,pctl-offset = <0x060>; + samsung,pin-count = <7>; + samsung,bank-type = <&bank_off>; + #gpio-cells = <2>; + + interrupt-controller; + samsung,eint-offset = <0x0C>; + #interrupt-cells = <2>; + }; + + gpk2: gpk2 { + gpio-controller; + samsung,pctl-offset = <0x080>; + samsung,pin-count = <7>; + samsung,bank-type = <&bank_off>; + #gpio-cells = <2>; + + interrupt-controller; + samsung,eint-offset = <0x10>; + #interrupt-cells = <2>; + }; + + gpk3: gpk3 { + gpio-controller; + samsung,pctl-offset = <0x0A0>; + samsung,pin-count = <7>; + samsung,bank-type = <&bank_off>; + #gpio-cells = <2>; + + interrupt-controller; + samsung,eint-offset = <0x14>; + #interrupt-cells = <2>; + }; + + gpl0: gpl0 { + gpio-controller; + samsung,pctl-offset = <0x0C0>; + samsung,pin-count = <7>; + samsung,bank-type = <&bank_off>; + #gpio-cells = <2>; + + interrupt-controller; + samsung,eint-offset = <0x18>; + #interrupt-cells = <2>; + }; + + gpl1: gpl1 { + gpio-controller; + samsung,pctl-offset = <0x0E0>; + samsung,pin-count = <2>; + samsung,bank-type = <&bank_off>; + #gpio-cells = <2>; + + interrupt-controller; + samsung,eint-offset = <0x1C>; + #interrupt-cells = <2>; + }; + + gpl2: gpl2 { + gpio-controller; + samsung,pctl-offset = <0x100>; + samsung,pin-count = <8>; + samsung,bank-type = <&bank_off>; + #gpio-cells = <2>; + + interrupt-controller; + samsung,eint-offset = <0x20>; + #interrupt-cells = <2>; + }; + + gpy0: gpy0 { + gpio-controller; + samsung,pctl-offset = <0x120>; + samsung,pin-count = <6>; + samsung,bank-type = <&bank_off>; + #gpio-cells = <2>; + }; + + gpy1: gpy1 { + gpio-controller; + samsung,pctl-offset = <0x140>; + samsung,pin-count = <4>; + samsung,bank-type = <&bank_off>; + #gpio-cells = <2>; + }; + + gpy2: gpy2 { + gpio-controller; + samsung,pctl-offset = <0x160>; + samsung,pin-count = <6>; + samsung,bank-type = <&bank_off>; + #gpio-cells = <2>; + }; + + gpy3: gpy3 { + gpio-controller; + samsung,pctl-offset = <0x180>; + samsung,pin-count = <8>; + samsung,bank-type = <&bank_off>; + #gpio-cells = <2>; + }; + + gpy4: gpy4 { + gpio-controller; + samsung,pctl-offset = <0x1A0>; + samsung,pin-count = <8>; + samsung,bank-type = <&bank_off>; + #gpio-cells = <2>; + }; + + gpy5: gpy5 { + gpio-controller; + samsung,pctl-offset = <0x1C0>; + samsung,pin-count = <8>; + samsung,bank-type = <&bank_off>; + #gpio-cells = <2>; + }; + + gpy6: gpy6 { + gpio-controller; + samsung,pctl-offset = <0x1E0>; + samsung,pin-count = <8>; + samsung,bank-type = <&bank_off>; + #gpio-cells = <2>; + }; + + gpx0: gpx0 { + gpio-controller; + samsung,pctl-offset = <0xC00>; + samsung,pin-count = <8>; + samsung,bank-type = <&bank_alive>; + #gpio-cells = <2>; + + interrupt-controller; + samsung,wkup-eint; + interrupt-parent = <&gic>; + interrupts = <0 16 0>, <0 17 0>, <0 18 0>, <0 19 0>, + <0 20 0>, <0 21 0>, <0 22 0>, <0 23 0>; + samsung,eint-offset = <0x00>; + #interrupt-cells = <2>; + }; + + gpx1: gpx1 { + gpio-controller; + samsung,pctl-offset = <0xC20>; + samsung,pin-count = <8>; + samsung,bank-type = <&bank_alive>; + #gpio-cells = <2>; + + interrupt-controller; + samsung,wkup-eint; + interrupt-parent = <&gic>; + interrupts = <0 24 0>, <0 25 0>, <0 26 0>, <0 27 0>, + <0 28 0>, <0 29 0>, <0 30 0>, <0 31 0>; + samsung,eint-offset = <0x04>; + #interrupt-cells = <2>; + }; + + gpx2: gpx2 { + gpio-controller; + samsung,pctl-offset = <0xC40>; + samsung,pin-count = <8>; + samsung,bank-type = <&bank_alive>; + #gpio-cells = <2>; + + interrupt-controller; + samsung,wkup-eint; + samsung,eint-offset = <0x08>; + #interrupt-cells = <2>; + }; + + gpx3: gpx3 { + gpio-controller; + samsung,pctl-offset = <0xC60>; + samsung,pin-count = <8>; + samsung,bank-type = <&bank_alive>; + #gpio-cells = <2>; + + interrupt-controller; + samsung,wkup-eint; + samsung,eint-offset = <0x0C>; + #interrupt-cells = <2>; + }; + }; + + pinctrl at 03860000 { + gpz: gpz { + gpio-controller; + samsung,pctl-offset = <0x000>; + samsung,pin-count = <7>; + samsung,bank-type = <&bank_off>; + #gpio-cells = <2>; + }; + }; +};
arch/arm/boot/dts/exynos4210-pinctrl.dtsi +2 -0
@@ -14,6 +14,8 @@ * published by the Free Software Foundation. */ +/include/ "exynos4210-pinctrl-banks.dtsi" + / { pinctrl at 11400000 { uart0_data: uart0-data {
arch/arm/boot/dts/exynos4210.dtsi +13 -12
@@ -58,27 +58,28 @@ compatible = "samsung,pinctrl-exynos4210"; reg = <0x11400000 0x1000>; interrupts = <0 47 0>; - interrupt-controller; - #interrupt-cells = <2>; + samsung,geint-con = <0x700>; + samsung,geint-mask = <0x900>; + samsung,geint-pend = <0xA00>; + samsung,svc = <0xB08>; }; pinctrl_1: pinctrl at 11000000 { compatible = "samsung,pinctrl-exynos4210"; reg = <0x11000000 0x1000>; interrupts = <0 46 0>; - interrupt-controller; - #interrupt-cells = <2>; + samsung,geint-con = <0x700>; + samsung,geint-mask = <0x900>; + samsung,geint-pend = <0xA00>; + samsung,svc = <0xB08>; - wakup_eint: wakeup-interrupt-controller { + wakeup-interrupt-controller { compatible = "samsung,exynos4210-wakeup-eint"; interrupt-parent = <&gic>; - interrupt-controller; - #interrupt-cells = <2>; - interrupts = <0 16 0>, <0 17 0>, <0 18 0>, <0 19 0>, - <0 20 0>, <0 21 0>, <0 22 0>, <0 23 0>, - <0 24 0>, <0 25 0>, <0 26 0>, <0 27 0>, - <0 28 0>, <0 29 0>, <0 30 0>, <0 31 0>, - <0 32 0>; + interrupts = <0 32 0>; + samsung,weint-con = <0xE00>; + samsung,weint-mask = <0xF00>; + samsung,weint-pend = <0xF40>; }; };
Signature · 1 line
1.7.12
RFC PATCH 16/16 Documentation: Update samsung-pinctrl device tree bindings documentation
In reply to Tomasz Figa--- .../bindings/pinctrl/samsung-pinctrl.txt | 212 ++++++++++++++++++--- 1 file changed, 187 insertions(+), 25 deletions(-)
Documentation/devicetree/bindings/pinctrl/samsung-pinctrl.txt +187 -25
@@ -13,8 +13,35 @@ Required Properties: - reg: Base address of the pin controller hardware module and length of the address space it occupies. -- interrupts: interrupt specifier for the controller. The format and value of - the interrupt specifier depends on the interrupt parent for the controller. +- Pin bank types: Pin bank nodes reference pin bank types by their phandles to + determine low level bank parameters such as bit field availability and widths. + There is no restriction for placement of such nodes. A bank type node must + contain following properties: + + - samsung,reg-names: names of registers specified in samsung,reg-params + property. Allowed register names are: + - "func" - function configuration register (GPxCON) + - "dat" - input/output value register (GPxDAT) + - "pud" - pull-up/-down control register (GPxPUD) + - "drv" - driver strength control register (GPxDRV) + - "conpdn" - power-down state control register (GPxCONPDN) + - "pudpdn" - power-down pull-up/-down control register (GPxPUDPDN) + - samsung,reg-params: register specifiers for registers named by + samsung,reg-names property. Each specifier contains two cells: + - first cell: offset in bytes from first register of the bank + - second cell: bits in register used for single pin. + +- 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: + + - gpio-controller: identifies the node as a gpio controller and pin bank. + - samsung,pctrl-offset: offset to pin control registers of the bank. + - samsung,pin-count: number of pins in the bank. + - samsung,bank-type: phandle to a node defining bank type. + - #gpio-cells: number of cells in GPIO specifier. Since the generic GPIO + binding is used, the amount of cells must be specified as 2. See generic + GPIO binding documentation for description of particular cells. - Pin mux/config groups as child nodes: The pin mux (selecting pin function mode) and pin config (pull up/down, driver strength) settings are represented
@@ -72,16 +99,30 @@ used as system wakeup events. A. External GPIO Interrupts: For supporting external gpio interrupts, the following properties should be specified in the pin-controller device node. -- interrupt-controller: identifies the controller node as interrupt-parent. -- #interrupt-cells: the value of this property should be 2. - - First Cell: represents the external gpio interrupt number local to the - external gpio interrupt space of the controller. - - Second Cell: flags to identify the type of the interrupt - - 1 = rising edge triggered - - 2 = falling edge triggered - - 3 = rising and falling edge triggered - - 4 = high level triggered - - 8 = low level triggered + - samsung,geint-con: offset of first EXT_INTxx_CON register. + - samsung,geint-mask: offset of first EXT_INTxx_MASK register. + - samsung,geint-pend: offset of first EXT_INTxx_PEND register. + - samsung,svc: offset of EXT_INT_SERVICE register. + - interrupt-parent: phandle of the interrupt parent to which the external + GPIO interrupts are forwarded to. + - interrupts: interrupt specifier for the controller. The format and value of + the interrupt specifier depends on the interrupt parent for the controller. + + In addition, following properties must be present in node of every bank + of pins supporting GPIO interrupts: + + - interrupt-controller: identifies the controller node as interrupt-parent. + - samsung,eint-offset: offset of register related to this bank from first + CON/MASK/PEND register. + - #interrupt-cells: the value of this property should be 2. + - First Cell: represents the external gpio interrupt number local to the + external gpio interrupt space of the controller. + - Second Cell: flags to identify the type of the interrupt + - 1 = rising edge triggered + - 2 = falling edge triggered + - 3 = rising and falling edge triggered + - 4 = high level triggered + - 8 = low level triggered B. External Wakeup Interrupts: For supporting external wakeup interrupts, a child node representing the external wakeup interrupt controller should be
@@ -94,7 +135,18 @@ B. External Wakeup Interrupts: For supporting external wakeup interrupts, a found on Samsung Exynos4210 SoC. - interrupt-parent: phandle of the interrupt parent to which the external wakeup interrupts are forwarded to. + - interrupts: interrupt used by multiplexed wakeup interrupts. + - samsung,weint-con: offset of first wake-up EXT_INTxx_CON register. + - samsung,weint-mask: offset of first wake-up EXT_INTxx_MASK register. + - samsung,weint-pend: offset of first wake-up EXT_INTxx_PEND register. + + In addition, following properties must be present in node of every bank + of pins supporting wake-up interrupts: + - interrupt-controller: identifies the node as interrupt-parent. + - samsung,wkup-eint: marks the bank as supporting wake-up interrupts. + - samsung,eint-offset: offset of register related to this bank from first + wake-up CON/MASK/PEND register. - #interrupt-cells: the value of this property should be 2 - First Cell: represents the external wakeup interrupt number local to the external wakeup interrupt space of the controller.
@@ -105,17 +157,125 @@ B. External Wakeup Interrupts: For supporting external wakeup interrupts, a - 4 = high level triggered - 8 = low level triggered + Node of every bank of pins supporting direct wake-up interrupts (without + multiplexing) must contain following properties: + + - interrupt-parent: phandle of the interrupt parent to which the external + wakeup interrupts are forwarded to. + - interrupts: interrupts of the interrupt parent which are used for external + wakeup interrupts from pins of the bank, must contain interrupts for all + pins of the bank. + Aliases: All the pin controller nodes should be represented in the aliases node using the following format 'pinctrl{n}' where n is a unique number for the alias. +Example: Nodes for pin bank types: + + pinctrl-bank-types { + bank_off: bank-off { + samsung,reg-names = "func", "dat", "pud", + "drv", "conpdn", "pudpdn"; + samsung,reg-params = <0x00 4>, <0x04 1>, <0x08 2>, + <0x0C 2>, <0x10 2>, <0x14 2>; + }; + + bank_alive: bank-alive { + samsung,reg-names = "func", "dat", "pud", + "drv"; + samsung,reg-params = <0x00 4>, <0x04 1>, <0x08 2>, + <0x0C 2>; + }; + }; + +Example: A pin-controller node with pin banks: + + pinctrl_0: pinctrl at 11400000 { + compatible = "samsung,pinctrl-exynos4210"; + reg = <0x11400000 0x1000>; + interrupts = <0 47 0>; + samsung,geint-con = <0x700>; + samsung,geint-mask = <0x900>; + samsung,geint-pend = <0xA00>; + samsung,svc = <0xB08>; + + /* ... */ + + /* Pin bank without external interrupts */ + gpy0: gpy0 { + gpio-controller; + samsung,pctl-offset = <0x120>; + samsung,pin-count = <6>; + samsung,bank-type = <&bank_off>; + #gpio-cells = <2>; + }; + + /* ... */ + + /* Pin bank with external GPIO interrupts */ + gpj0: gpj0 { + gpio-controller; + samsung,pctl-offset = <0x000>; + samsung,pin-count = <8>; + samsung,bank-type = <&bank_off>; + #gpio-cells = <2>; + + interrupt-controller; + samsung,eint-offset = <0x00>; + #interrupt-cells = <2>; + }; + + /* ... */ + + /* Pin bank with external direct wake-up interrupts */ + gpx0: gpx0 { + gpio-controller; + samsung,pctl-offset = <0xC00>; + samsung,pin-count = <8>; + samsung,bank-type = <&bank_alive>; + #gpio-cells = <2>; + + interrupt-controller; + samsung,wkup-eint; + interrupt-parent = <&gic>; + interrupts = <0 16 0>, <0 17 0>, <0 18 0>, <0 19 0>, + <0 20 0>, <0 21 0>, <0 22 0>, <0 23 0>; + samsung,eint-offset = <0x00>; + #interrupt-cells = <2>; + }; + + /* ... */ + + /* Pin bank with external multiplexed wake-up interrupts */ + gpx2: gpx2 { + gpio-controller; + samsung,pctl-offset = <0xC40>; + samsung,pin-count = <8>; + samsung,bank-type = <&bank_alive>; + #gpio-cells = <2>; + + interrupt-controller; + samsung,wkup-eint; + samsung,eint-offset = <0x08>; + #interrupt-cells = <2>; + }; + + /* ... */ + }; + Example 1: A pin-controller node with pin groups. pinctrl_0: pinctrl at 11400000 { compatible = "samsung,pinctrl-exynos4210"; reg = <0x11400000 0x1000>; interrupts = <0 47 0>; + samsung,geint-con = <0x700>; + samsung,geint-mask = <0x900>; + samsung,geint-pend = <0xA00>; + samsung,svc = <0xB08>; + + /* ... */ uart0_data: uart0-data { samsung,pins = "gpa0-0", "gpa0-1";
@@ -158,20 +318,21 @@ Example 2: A pin-controller node with external wakeup interrupt controller node. pinctrl_1: pinctrl at 11000000 { compatible = "samsung,pinctrl-exynos4210"; reg = <0x11000000 0x1000>; - interrupts = <0 46 0>; - interrupt-controller; - #interrupt-cells = <2>; + interrupts = <0 46 0> + samsung,geint-con = <0x700>; + samsung,geint-mask = <0x900>; + samsung,geint-pend = <0xA00>; + samsung,svc = <0xB08>; - wakup_eint: wakeup-interrupt-controller { + /* ... */ + + wakeup-interrupt-controller { compatible = "samsung,exynos4210-wakeup-eint"; interrupt-parent = <&gic>; - interrupt-controller; - #interrupt-cells = <2>; - interrupts = <0 16 0>, <0 17 0>, <0 18 0>, <0 19 0>, - <0 20 0>, <0 21 0>, <0 22 0>, <0 23 0>, - <0 24 0>, <0 25 0>, <0 26 0>, <0 27 0>, - <0 28 0>, <0 29 0>, <0 30 0>, <0 31 0>, - <0 32 0>; + interrupts = <0 32 0>; + samsung,weint-con = <0xE00>; + samsung,weint-mask = <0xF00>; + samsung,weint-pend = <0xF40>; }; };
@@ -190,7 +351,8 @@ Example 4: Set up the default pin state for uart controller. static int s3c24xx_serial_probe(struct platform_device *pdev) { struct pinctrl *pinctrl; - ... - ... + + /* ... */ + pinctrl = devm_pinctrl_get_select_default(&pdev->dev); }
Signature · 1 line
1.7.12
RFC PATCH 16/16 Documentation: Update samsung-pinctrl device tree bindings documentation
Quoted 1 line · Tomasz Figa
Signed-off-by Tomasz Figa <[email protected]>
I think this binding looks reasonable now.
I'm not sure if this series works with "git bisect" though? For example, perhaps you want to move patch 15 to the start so the new properties are present before the code attempts to use them.
cover pinctrl: samsung: Usability and extensibiltiy improvements
In reply to Tomasz FigaQuoted 5 lines · Tomasz Figa
This RFC series is a work on improving usability and extensibiltiy of the pinctrl-samsung driver. It consists of three main parts:
- moving SoC-specific data to device tree
- converting the driver to use one GPIO chip and one IRQ domain per pin bank
- introducing generic wake-up interrupt capability description
Overall this looks good to me.
Yours,
Linus Walleij