Skip to contentSkip to conversation

pinctrl: samsung: Convert the driver to use per-bank GPIO and interrupt specifiers

RFC PATCH New Tomasz Figa 4 participants 11 messages Sep 21, 2012 – Sep 24, 2012

Subsystems (3)
lore
Share & tools
lore
#0 lore raw

cover pinctrl: samsung: Convert the driver to use per-bank GPIO and interrupt specifiers

This is a continuation of work focused on improving the pinctrl-samsung driver.

First part on which this one depends:
[RFC 0/6] pinctrl: samsung: Remove static platform-specific data
http://article.gmane.org/gmane.linux.kernel.samsung-soc/12759

This series 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.

Any comments are welcome.

To do:
- Bindings documentation
- Per-bank interrupt specifiers for wake-up interrupts
- Configuration of pins used as wake-up interrupts to EINT function

Tomasz Figa (6):
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
ARM: dts: exynos4210: Update pin bank nodes to reflect per-bank GPIO
chips and IRQ domains

 arch/arm/boot/dts/exynos4210-pinctrl-banks.dtsi |  72 ++++++++++
 arch/arm/boot/dts/exynos4210.dtsi               |   4 -
 drivers/pinctrl/pinctrl-exynos.c                | 118 +++++------------
 drivers/pinctrl/pinctrl-exynos.h                |  12 --
 drivers/pinctrl/pinctrl-samsung.c               | 168 ++++++++++++++----------
 drivers/pinctrl/pinctrl-samsung.h               |  18 ++-
 6 files changed, 220 insertions(+), 172 deletions(-)
Signature · 1 line
1.7.12
#1 lore raw

RFC PATCH 1/6 pinctrl: samsung: Hold OF node of pin bank in bank struct

The node pointer will be used in extensions added by patches that will follow.

---
 drivers/pinctrl/pinctrl-samsung.c | 2 ++
 drivers/pinctrl/pinctrl-samsung.h | 3 +++
 2 files changed, 5 insertions(+)
drivers/pinctrl/pinctrl-samsung.c +2 -0
index 03bf743..846b277 100644
@@ -825,6 +825,8 @@ static int samsung_pinctrl_parse_dt_bank(struct samsung_pin_bank *bank,
 	if (!ret)
 		bank->pudpdn_width = val;
 
+	bank->of_node = np;
+
 	if (!of_find_property(np, "interrupt-controller", NULL)) {
 		bank->eint_type = EINT_TYPE_NONE;
 		return 0;
drivers/pinctrl/pinctrl-samsung.h +3 -0
index 72303f1..b7b74cc 100644
@@ -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
#2 lore raw

RFC PATCH 2/6 pinctrl: samsung: Hold pointer to driver data in bank struct

In reply to Tomasz Figa

The pointer will be used by further extensions added to the driver.

---
 drivers/pinctrl/pinctrl-samsung.c | 33 +++++++++++++++++----------------
 drivers/pinctrl/pinctrl-samsung.h |  2 ++
 2 files changed, 19 insertions(+), 16 deletions(-)
drivers/pinctrl/pinctrl-samsung.c +17 -16
index 846b277..3f48d3f 100644
@@ -844,11 +844,11 @@ 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 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 = d->dev->of_node;
 	struct device_node *bank_np;
 	struct samsung_pin_ctrl *ctrl;
 	struct samsung_pin_bank *banks, *b;
@@ -858,9 +858,9 @@ 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");
+		dev_err(d->dev, "failed to get alias id\n");
 		return NULL;
 	}
 	match = of_match_node(samsung_pinctrl_dt_match, node);
@@ -873,20 +873,20 @@ static struct samsung_pin_ctrl *samsung_pinctrl_get_soc_data(
 	}
 
 	if (!bank_cnt) {
-		dev_err(&pdev->dev, "no pin banks specified\n");
+		dev_err(d->dev, "no pin banks specified\n");
 		return NULL;
 	}
 
-	ctrl = devm_kzalloc(&pdev->dev, sizeof(*ctrl), GFP_KERNEL);
+	ctrl = devm_kzalloc(d->dev, sizeof(*ctrl), GFP_KERNEL);
 	if (!ctrl) {
-		dev_err(&pdev->dev, "failed to allocate soc data\n");
+		dev_err(d->dev, "failed to allocate soc data\n");
 		return NULL;
 	}
 
-	banks = devm_kzalloc(&pdev->dev,
+	banks = devm_kzalloc(d->dev,
 			bank_cnt * sizeof(*ctrl->pin_banks), GFP_KERNEL);
 	if (!banks) {
-		dev_err(&pdev->dev, "failed to allocate pin banks\n");
+		dev_err(d->dev, "failed to allocate pin banks\n");
 		return NULL;
 	}
 
@@ -896,6 +896,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 (of_find_property(bank_np, "interrupt-controller", NULL)) {
@@ -956,21 +957,21 @@ 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;
 	}
-	drvdata->ctrl = ctrl;
 	drvdata->dev = dev;
 
+	ctrl = samsung_pinctrl_get_soc_data(drvdata);
+	if (!ctrl) {
+		dev_err(&pdev->dev, "driver data not available\n");
+		return -EINVAL;
+	}
+	drvdata->ctrl = ctrl;
+
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	if (!res) {
 		dev_err(dev, "cannot find IO resource\n");
drivers/pinctrl/pinctrl-samsung.h +2 -0
index b7b74cc..9e30081 100644
@@ -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
#3 lore raw

RFC PATCH 3/6 pinctrl: exynos: Use one IRQ domain per pin bank

In reply to Tomasz Figa

Instead 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  | 118 +++++++++++---------------------------
 drivers/pinctrl/pinctrl-exynos.h  |  12 ----
 drivers/pinctrl/pinctrl-samsung.c |   4 +-
 drivers/pinctrl/pinctrl-samsung.h |   5 +-
 4 files changed, 37 insertions(+), 102 deletions(-)
drivers/pinctrl/pinctrl-exynos.c +34 -84
index 340bfc2..2f8427f 100644
@@ -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_handler_data(irqd);
+	struct samsung_pinctrl_drv_data *d = irq_data_get_irq_chip_data(irqd);
+	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_handler_data(irqd);
+	struct samsung_pinctrl_drv_data *d = irq_data_get_irq_chip_data(irqd);
+	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_handler_data(irqd);
+	struct samsung_pinctrl_drv_data *d = irq_data_get_irq_chip_data(irqd);
+	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_handler_data(irqd);
+	struct samsung_pinctrl_drv_data *d = irq_data_get_irq_chip_data(irqd);
 	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,24 @@ 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;
+	struct samsung_pin_bank *b = h->host_data;
 
-	eint_data = exynos_get_eint_data(hw, d);
-	if (!eint_data)
-		return -EINVAL;
-
-	irq_set_handler_data(virq, eint_data);
-	irq_set_chip_data(virq, h->host_data);
+	irq_set_handler_data(virq, b);
+	irq_set_chip_data(virq, b->drvdata);
 	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 +172,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->gpio_irqd, pin);
 	if (!virq)
 		return IRQ_NONE;
 	generic_handle_irq(virq);
@@ -242,8 +185,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 +202,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->gpio_irqd = irq_domain_add_linear(bank->of_node,
+				bank->nr_pins, &exynos_gpio_irqd_ops, bank);
+		if (!bank->gpio_irqd) {
+			dev_err(dev, "gpio irq domain add failed\n");
+			return -ENXIO;
+		}
 	}
 
 	return 0;
drivers/pinctrl/pinctrl-exynos.h +0 -12
index a72cfc7..30aca2b 100644
@@ -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 -3
index 3f48d3f..a6c219a 100644
@@ -899,10 +899,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 (of_find_property(bank_np, "interrupt-controller", NULL)) {
-			b->irq_base = eint_cnt;
+		if (of_find_property(bank_np, "interrupt-controller", NULL))
 			eint_cnt += b->nr_pins;
-		}
 		++b;
 	}
 
drivers/pinctrl/pinctrl-samsung.h +2 -3
index 9e30081..7dbdef9 100644
@@ -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
+ * @gpio_irqd: GPIO IRQ domain of pin 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 *gpio_irqd;
 };
 
 /**
@@ -218,7 +218,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
#4 lore raw

RFC PATCH 4/6 pinctrl: samsung: Do not pass gpio_chip to pin_to_reg_bank

In reply to Tomasz Figa

The 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
index a6c219a..eadcef7 100644
@@ -255,14 +255,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) &&
@@ -297,7 +295,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,
 				&reg, &pin_offset, &bank);
 		mask = (1 << bank->func_width) - 1;
 		shift = pin_offset * bank->func_width;
@@ -334,10 +332,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, &reg, &pin_offset, &bank);
+	drvdata = pinctrl_dev_get_drvdata(pctldev);
+
+	pin_to_reg_bank(drvdata, offset, &reg, &pin_offset, &bank);
 	mask = (1 << bank->func_width) - 1;
 	shift = pin_offset * bank->func_width;
 
@@ -371,7 +372,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, &reg_base,
+	pin_to_reg_bank(drvdata, pin - drvdata->ctrl->base, &reg_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, &reg, &pin_offset, NULL);
+	drvdata = dev_get_drvdata(gc->dev);
+
+	pin_to_reg_bank(drvdata, offset, &reg, &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, &reg, &pin_offset, NULL);
+	pin_to_reg_bank(drvdata, offset, &reg, &pin_offset, NULL);
 	data = readl(reg + DAT_REG);
 	data >>= pin_offset;
 	data &= 1;
Signature · 1 line
1.7.12
#5 lore raw

RFC PATCH 5/6 pinctrl: samsung: Use one GPIO chip per pin bank

In reply to Tomasz Figa

This 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 |   8 ++-
 2 files changed, 78 insertions(+), 48 deletions(-)
drivers/pinctrl/pinctrl-samsung.c +73 -45
index eadcef7..426a13d 100644
@@ -51,6 +51,11 @@ DEFINE_SPINLOCK(init_lock);
 
 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)
 {
@@ -336,9 +341,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, &reg, &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, &reg, &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, &reg, &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 +5 -3
index 7dbdef9..a6072aa 100644
@@ -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
@@ -130,6 +132,9 @@ struct samsung_pin_bank {
 	struct device_node *of_node;
 	struct samsung_pinctrl_drv_data *drvdata;
 	struct irq_domain *gpio_irqd;
+
+	struct gpio_chip gpio_chip;
+	struct pinctrl_gpio_range grange;
 };
 
 /**
@@ -219,9 +224,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
#6 lore raw

RFC PATCH 6/6 ARM: dts: exynos4210: Update pin bank nodes to reflect per-bank GPIO chips and IRQ domains

In reply to Tomasz Figa

This patch modifies device tree sources of Exynos4210 to match the changes done to pinctrl-samsung driver.

---
 arch/arm/boot/dts/exynos4210-pinctrl-banks.dtsi | 72 +++++++++++++++++++++++++
 arch/arm/boot/dts/exynos4210.dtsi               |  4 --
 2 files changed, 72 insertions(+), 4 deletions(-)
arch/arm/boot/dts/exynos4210-pinctrl-banks.dtsi +72 -0
index cac7f71..c3795e4 100644
@@ -24,9 +24,11 @@
 			samsung,drv-width = <2>;
 			samsung,conpdn-width = <2>;
 			samsung,pudpdn-width = <2>;
+			#gpio-cells = <2>;
 
 			interrupt-controller;
 			samsung,eint-offset = <0x00>;
+			#interrupt-cells = <2>;
 		};
 
 		gpa1: pin-bank at 1 {
@@ -39,9 +41,11 @@
 			samsung,drv-width = <2>;
 			samsung,conpdn-width = <2>;
 			samsung,pudpdn-width = <2>;
+			#gpio-cells = <2>;
 
 			interrupt-controller;
 			samsung,eint-offset = <0x04>;
+			#interrupt-cells = <2>;
 		};
 
 		gpb: pin-bank at 2 {
@@ -54,9 +58,11 @@
 			samsung,drv-width = <2>;
 			samsung,conpdn-width = <2>;
 			samsung,pudpdn-width = <2>;
+			#gpio-cells = <2>;
 
 			interrupt-controller;
 			samsung,eint-offset = <0x08>;
+			#interrupt-cells = <2>;
 		};
 
 		gpc0: pin-bank at 3 {
@@ -69,9 +75,11 @@
 			samsung,drv-width = <2>;
 			samsung,conpdn-width = <2>;
 			samsung,pudpdn-width = <2>;
+			#gpio-cells = <2>;
 
 			interrupt-controller;
 			samsung,eint-offset = <0x0C>;
+			#interrupt-cells = <2>;
 		};
 
 		gpc1: pin-bank at 4 {
@@ -84,9 +92,11 @@
 			samsung,drv-width = <2>;
 			samsung,conpdn-width = <2>;
 			samsung,pudpdn-width = <2>;
+			#gpio-cells = <2>;
 
 			interrupt-controller;
 			samsung,eint-offset = <0x10>;
+			#interrupt-cells = <2>;
 		};
 
 		gpd0: pin-bank at 5 {
@@ -99,9 +109,11 @@
 			samsung,drv-width = <2>;
 			samsung,conpdn-width = <2>;
 			samsung,pudpdn-width = <2>;
+			#gpio-cells = <2>;
 
 			interrupt-controller;
 			samsung,eint-offset = <0x14>;
+			#interrupt-cells = <2>;
 		};
 
 		gpd1: pin-bank at 6 {
@@ -114,9 +126,11 @@
 			samsung,drv-width = <2>;
 			samsung,conpdn-width = <2>;
 			samsung,pudpdn-width = <2>;
+			#gpio-cells = <2>;
 
 			interrupt-controller;
 			samsung,eint-offset = <0x18>;
+			#interrupt-cells = <2>;
 		};
 
 		gpe0: pin-bank at 7 {
@@ -129,9 +143,11 @@
 			samsung,drv-width = <2>;
 			samsung,conpdn-width = <2>;
 			samsung,pudpdn-width = <2>;
+			#gpio-cells = <2>;
 
 			interrupt-controller;
 			samsung,eint-offset = <0x1C>;
+			#interrupt-cells = <2>;
 		};
 
 		gpe1: pin-bank at 8 {
@@ -144,9 +160,11 @@
 			samsung,drv-width = <2>;
 			samsung,conpdn-width = <2>;
 			samsung,pudpdn-width = <2>;
+			#gpio-cells = <2>;
 
 			interrupt-controller;
 			samsung,eint-offset = <0x20>;
+			#interrupt-cells = <2>;
 		};
 
 		gpe2: pin-bank at 9 {
@@ -159,9 +177,11 @@
 			samsung,drv-width = <2>;
 			samsung,conpdn-width = <2>;
 			samsung,pudpdn-width = <2>;
+			#gpio-cells = <2>;
 
 			interrupt-controller;
 			samsung,eint-offset = <0x24>;
+			#interrupt-cells = <2>;
 		};
 
 		gpe3: pin-bank at 10 {
@@ -174,9 +194,11 @@
 			samsung,drv-width = <2>;
 			samsung,conpdn-width = <2>;
 			samsung,pudpdn-width = <2>;
+			#gpio-cells = <2>;
 
 			interrupt-controller;
 			samsung,eint-offset = <0x28>;
+			#interrupt-cells = <2>;
 		};
 
 		gpe4: pin-bank at 11 {
@@ -189,9 +211,11 @@
 			samsung,drv-width = <2>;
 			samsung,conpdn-width = <2>;
 			samsung,pudpdn-width = <2>;
+			#gpio-cells = <2>;
 
 			interrupt-controller;
 			samsung,eint-offset = <0x2C>;
+			#interrupt-cells = <2>;
 		};
 
 		gpf0: pin-bank at 12 {
@@ -204,9 +228,11 @@
 			samsung,drv-width = <2>;
 			samsung,conpdn-width = <2>;
 			samsung,pudpdn-width = <2>;
+			#gpio-cells = <2>;
 
 			interrupt-controller;
 			samsung,eint-offset = <0x30>;
+			#interrupt-cells = <2>;
 		};
 
 		gpf1: pin-bank at 13 {
@@ -219,9 +245,11 @@
 			samsung,drv-width = <2>;
 			samsung,conpdn-width = <2>;
 			samsung,pudpdn-width = <2>;
+			#gpio-cells = <2>;
 
 			interrupt-controller;
 			samsung,eint-offset = <0x34>;
+			#interrupt-cells = <2>;
 		};
 
 		gpf2: pin-bank at 14 {
@@ -234,9 +262,11 @@
 			samsung,drv-width = <2>;
 			samsung,conpdn-width = <2>;
 			samsung,pudpdn-width = <2>;
+			#gpio-cells = <2>;
 
 			interrupt-controller;
 			samsung,eint-offset = <0x38>;
+			#interrupt-cells = <2>;
 		};
 
 		gpf3: pin-bank at 15 {
@@ -249,9 +279,11 @@
 			samsung,drv-width = <2>;
 			samsung,conpdn-width = <2>;
 			samsung,pudpdn-width = <2>;
+			#gpio-cells = <2>;
 
 			interrupt-controller;
 			samsung,eint-offset = <0x3C>;
+			#interrupt-cells = <2>;
 		};
 	};
 
@@ -266,9 +298,11 @@
 			samsung,drv-width = <2>;
 			samsung,conpdn-width = <2>;
 			samsung,pudpdn-width = <2>;
+			#gpio-cells = <2>;
 
 			interrupt-controller;
 			samsung,eint-offset = <0x00>;
+			#interrupt-cells = <2>;
 		};
 
 		gpj1: pin-bank at 1 {
@@ -281,9 +315,11 @@
 			samsung,drv-width = <2>;
 			samsung,conpdn-width = <2>;
 			samsung,pudpdn-width = <2>;
+			#gpio-cells = <2>;
 
 			interrupt-controller;
 			samsung,eint-offset = <0x04>;
+			#interrupt-cells = <2>;
 		};
 
 		gpk0: pin-bank at 2 {
@@ -296,9 +332,11 @@
 			samsung,drv-width = <2>;
 			samsung,conpdn-width = <2>;
 			samsung,pudpdn-width = <2>;
+			#gpio-cells = <2>;
 
 			interrupt-controller;
 			samsung,eint-offset = <0x08>;
+			#interrupt-cells = <2>;
 		};
 
 		gpk1: pin-bank at 3 {
@@ -311,9 +349,11 @@
 			samsung,drv-width = <2>;
 			samsung,conpdn-width = <2>;
 			samsung,pudpdn-width = <2>;
+			#gpio-cells = <2>;
 
 			interrupt-controller;
 			samsung,eint-offset = <0x0C>;
+			#interrupt-cells = <2>;
 		};
 
 		gpk2: pin-bank at 4 {
@@ -326,9 +366,11 @@
 			samsung,drv-width = <2>;
 			samsung,conpdn-width = <2>;
 			samsung,pudpdn-width = <2>;
+			#gpio-cells = <2>;
 
 			interrupt-controller;
 			samsung,eint-offset = <0x10>;
+			#interrupt-cells = <2>;
 		};
 
 		gpk3: pin-bank at 5 {
@@ -341,9 +383,11 @@
 			samsung,drv-width = <2>;
 			samsung,conpdn-width = <2>;
 			samsung,pudpdn-width = <2>;
+			#gpio-cells = <2>;
 
 			interrupt-controller;
 			samsung,eint-offset = <0x14>;
+			#interrupt-cells = <2>;
 		};
 
 		gpl0: pin-bank at 6 {
@@ -356,9 +400,11 @@
 			samsung,drv-width = <2>;
 			samsung,conpdn-width = <2>;
 			samsung,pudpdn-width = <2>;
+			#gpio-cells = <2>;
 
 			interrupt-controller;
 			samsung,eint-offset = <0x18>;
+			#interrupt-cells = <2>;
 		};
 
 		gpl1: pin-bank at 7 {
@@ -371,9 +417,11 @@
 			samsung,drv-width = <2>;
 			samsung,conpdn-width = <2>;
 			samsung,pudpdn-width = <2>;
+			#gpio-cells = <2>;
 
 			interrupt-controller;
 			samsung,eint-offset = <0x1C>;
+			#interrupt-cells = <2>;
 		};
 
 		gpl2: pin-bank at 8 {
@@ -386,9 +434,11 @@
 			samsung,drv-width = <2>;
 			samsung,conpdn-width = <2>;
 			samsung,pudpdn-width = <2>;
+			#gpio-cells = <2>;
 
 			interrupt-controller;
 			samsung,eint-offset = <0x20>;
+			#interrupt-cells = <2>;
 		};
 
 		gpm0: pin-bank at 9 {
@@ -401,9 +451,11 @@
 			samsung,drv-width = <2>;
 			samsung,conpdn-width = <2>;
 			samsung,pudpdn-width = <2>;
+			#gpio-cells = <2>;
 
 			interrupt-controller;
 			samsung,eint-offset = <0x24>;
+			#interrupt-cells = <2>;
 		};
 
 		gpm1: pin-bank at 10 {
@@ -416,9 +468,11 @@
 			samsung,drv-width = <2>;
 			samsung,conpdn-width = <2>;
 			samsung,pudpdn-width = <2>;
+			#gpio-cells = <2>;
 
 			interrupt-controller;
 			samsung,eint-offset = <0x28>;
+			#interrupt-cells = <2>;
 		};
 
 		gpm2: pin-bank at 11 {
@@ -431,9 +485,11 @@
 			samsung,drv-width = <2>;
 			samsung,conpdn-width = <2>;
 			samsung,pudpdn-width = <2>;
+			#gpio-cells = <2>;
 
 			interrupt-controller;
 			samsung,eint-offset = <0x2C>;
+			#interrupt-cells = <2>;
 		};
 
 		gpm3: pin-bank at 12 {
@@ -446,9 +502,11 @@
 			samsung,drv-width = <2>;
 			samsung,conpdn-width = <2>;
 			samsung,pudpdn-width = <2>;
+			#gpio-cells = <2>;
 
 			interrupt-controller;
 			samsung,eint-offset = <0x30>;
+			#interrupt-cells = <2>;
 		};
 
 		gpm4: pin-bank at 13 {
@@ -461,9 +519,11 @@
 			samsung,drv-width = <2>;
 			samsung,conpdn-width = <2>;
 			samsung,pudpdn-width = <2>;
+			#gpio-cells = <2>;
 
 			interrupt-controller;
 			samsung,eint-offset = <0x34>;
+			#interrupt-cells = <2>;
 		};
 
 		gpy0: pin-bank at 14 {
@@ -476,6 +536,7 @@
 			samsung,drv-width = <2>;
 			samsung,conpdn-width = <2>;
 			samsung,pudpdn-width = <2>;
+			#gpio-cells = <2>;
 		};
 
 		gpy1: pin-bank at 15 {
@@ -488,6 +549,7 @@
 			samsung,drv-width = <2>;
 			samsung,conpdn-width = <2>;
 			samsung,pudpdn-width = <2>;
+			#gpio-cells = <2>;
 		};
 
 		gpy2: pin-bank at 16 {
@@ -500,6 +562,7 @@
 			samsung,drv-width = <2>;
 			samsung,conpdn-width = <2>;
 			samsung,pudpdn-width = <2>;
+			#gpio-cells = <2>;
 		};
 
 		gpy3: pin-bank at 17 {
@@ -512,6 +575,7 @@
 			samsung,drv-width = <2>;
 			samsung,conpdn-width = <2>;
 			samsung,pudpdn-width = <2>;
+			#gpio-cells = <2>;
 		};
 
 		gpy4: pin-bank at 18 {
@@ -524,6 +588,7 @@
 			samsung,drv-width = <2>;
 			samsung,conpdn-width = <2>;
 			samsung,pudpdn-width = <2>;
+			#gpio-cells = <2>;
 		};
 
 		gpy5: pin-bank at 19{
@@ -536,6 +601,7 @@
 			samsung,drv-width = <2>;
 			samsung,conpdn-width = <2>;
 			samsung,pudpdn-width = <2>;
+			#gpio-cells = <2>;
 		};
 
 		gpy6: pin-bank at 20 {
@@ -548,6 +614,7 @@
 			samsung,drv-width = <2>;
 			samsung,conpdn-width = <2>;
 			samsung,pudpdn-width = <2>;
+			#gpio-cells = <2>;
 		};
 
 		gpx0: pin-bank at 21 {
@@ -558,6 +625,7 @@
 			samsung,func-width = <4>;
 			samsung,pud-width = <2>;
 			samsung,drv-width = <2>;
+			#gpio-cells = <2>;
 		};
 
 		gpx1: pin-bank at 22 {
@@ -568,6 +636,7 @@
 			samsung,func-width = <4>;
 			samsung,pud-width = <2>;
 			samsung,drv-width = <2>;
+			#gpio-cells = <2>;
 		};
 
 		gpx2: pin-bank at 23 {
@@ -578,6 +647,7 @@
 			samsung,func-width = <4>;
 			samsung,pud-width = <2>;
 			samsung,drv-width = <2>;
+			#gpio-cells = <2>;
 		};
 
 		gpx3: pin-bank at 24 {
@@ -588,6 +658,7 @@
 			samsung,func-width = <4>;
 			samsung,pud-width = <2>;
 			samsung,drv-width = <2>;
+			#gpio-cells = <2>;
 		};
 	};
 
@@ -600,6 +671,7 @@
 			samsung,func-width = <4>;
 			samsung,pud-width = <2>;
 			samsung,drv-width = <2>;
+			#gpio-cells = <2>;
 		};
 	};
 };
arch/arm/boot/dts/exynos4210.dtsi +0 -4
index 0e93717..de6308b 100644
@@ -58,24 +58,20 @@
 		compatible = "samsung,pinctrl-exynos4210";
 		reg = <0x11400000 0x1000>;
 		interrupts = <0 47 0>;
-		interrupt-controller;
 		samsung,geint-con = <0x700>;
 		samsung,geint-mask = <0x900>;
 		samsung,geint-pend = <0xA00>;
 		samsung,svc = <0xB08>;
-		#interrupt-cells = <2>;
 	};
 
 	pinctrl_1: pinctrl at 11000000 {
 		compatible = "samsung,pinctrl-exynos4210";
 		reg = <0x11000000 0x1000>;
 		interrupts = <0 46 0>;
-		interrupt-controller;
 		samsung,geint-con = <0x700>;
 		samsung,geint-mask = <0x900>;
 		samsung,geint-pend = <0xA00>;
 		samsung,svc = <0xB08>;
-		#interrupt-cells = <2>;
 
 		wakup_eint: wakeup-interrupt-controller {
 			compatible = "samsung,exynos4210-wakeup-eint";
Signature · 1 line
1.7.12
#8 lore raw

cover pinctrl: samsung: Convert the driver to use per-bank GPIO and interrupt specifiers

Quoted 7 lines · Linus Walleij
Quoted 2 lines · Tomasz Figa

This is a continuation of work focused on improving the pinctrl-samsung driver.

All look good to me, I guess these will go through the Samsung tree?

Now samsung tree is merged so if you don't mind, can you merge it by pinctl tree?

Thank you,
Kyungmin Park

#9 lore raw

cover pinctrl: samsung: Convert the driver to use per-bank GPIO and interrupt specifiers

Quoted 11 lines · Kyungmin Park
Quoted 7 lines · Linus Walleij
Quoted 2 lines · Tomasz Figa

This is a continuation of work focused on improving the pinctrl-samsung driver.

All look good to me, I guess these will go through the Samsung tree?

Now samsung tree is merged so if you don't mind, can you merge it by pinctl tree?

Yes but not until after the merge window... I have closed my tree.

I think all dependencies are in the ARM SoC tree now, so I suspect it wouldn't apply anyway?

Tomasz can you repost this after the merge window so I don't forget about applying it?

Yours,
Linus Walleij

#10 lore raw

cover pinctrl: samsung: Convert the driver to use per-bank GPIO and interrupt specifiers

In reply to Linus Walleij

Hi Linus,

Quoted 6 lines · On Monday 24 of September 2012 12:43:23 Linus Walleij wrote:
Quoted 2 lines · Tomasz Figa

This is a continuation of work focused on improving the pinctrl-samsung driver.

All look good to me, I guess these will go through the Samsung tree?

Hmm, these patches are just at RFC stage at the moment and depend on the first part which does somewhat heavy reorganization of the driver. So this is more like a proof of concept.

After we settle all the things being discussed I will send a ready patch series including both of these parts.

Thanks for your ack anyway.

Best regards,
Tomasz Figa