From 7c367d3da697846b80058859937f606c0081beda Mon Sep 17 00:00:00 2001 From: Tomasz Figa Date: Thu, 11 Oct 2012 10:11:07 +0200 Subject: [PATCH 01/32] pinctrl: samsung: Detect and handle unsupported configuration types This patch modifies the pinctrl-samsung driver to detect when width of a bit field is set to zero (which means that such configuraton type is not supported) and return an error instead of trying to modify an inexistent register. Signed-off-by: Tomasz Figa Reviewed-by: Kyungmin Park Acked-by: Thomas Abraham Signed-off-by: Linus Walleij --- drivers/pinctrl/pinctrl-samsung.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/pinctrl/pinctrl-samsung.c b/drivers/pinctrl/pinctrl-samsung.c index dd108a94acf..c660fa5071d 100644 --- a/drivers/pinctrl/pinctrl-samsung.c +++ b/drivers/pinctrl/pinctrl-samsung.c @@ -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); From 62f14c0ef5d1bbd640b42a59f8f084f764a067c4 Mon Sep 17 00:00:00 2001 From: Tomasz Figa Date: Thu, 11 Oct 2012 10:11:08 +0200 Subject: [PATCH 02/32] pinctrl: samsung: Do not pass gpio_chip to pin_to_reg_bank 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. Signed-off-by: Tomasz Figa Reviewed-by: Kyungmin Park Acked-by: Thomas Abraham Signed-off-by: Linus Walleij --- drivers/pinctrl/pinctrl-samsung.c | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/drivers/pinctrl/pinctrl-samsung.c b/drivers/pinctrl/pinctrl-samsung.c index c660fa5071d..aa42d54e89c 100644 --- a/drivers/pinctrl/pinctrl-samsung.c +++ b/drivers/pinctrl/pinctrl-samsung.c @@ -250,14 +250,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) && @@ -292,7 +290,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; @@ -329,10 +327,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; @@ -366,7 +367,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) { @@ -468,8 +469,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) @@ -482,8 +486,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; - 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 >>= pin_offset; data &= 1; From 40ba6227aeb3712b0cea0c4f9c3e355cf801f4c4 Mon Sep 17 00:00:00 2001 From: Tomasz Figa Date: Thu, 11 Oct 2012 10:11:09 +0200 Subject: [PATCH 03/32] pinctrl: samsung: Assing pin numbers dynamically This patch modifies the pinctrl-samsung driver to assign numbers to pins dynamically instead of static enumerations. Thanks to this change the amount of code requried to support a SoC can be greatly reduced and the code made more readable. Signed-off-by: Tomasz Figa Reviewed-by: Kyungmin Park Acked-by: Thomas Abraham Signed-off-by: Linus Walleij --- drivers/pinctrl/pinctrl-exynos.c | 83 ++++++++++++++----------------- drivers/pinctrl/pinctrl-exynos.h | 11 ++-- drivers/pinctrl/pinctrl-samsung.c | 22 +++++++- 3 files changed, 62 insertions(+), 54 deletions(-) diff --git a/drivers/pinctrl/pinctrl-exynos.c b/drivers/pinctrl/pinctrl-exynos.c index 21362f48d37..0ea2164bf6d 100644 --- a/drivers/pinctrl/pinctrl-exynos.c +++ b/drivers/pinctrl/pinctrl-exynos.c @@ -484,51 +484,51 @@ static int exynos_eint_wkup_init(struct samsung_pinctrl_drv_data *d) /* 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"), + EXYNOS_PIN_BANK_EINTG(8, 0x000, "gpa0"), + EXYNOS_PIN_BANK_EINTG(6, 0x020, "gpa1"), + EXYNOS_PIN_BANK_EINTG(8, 0x040, "gpb"), + EXYNOS_PIN_BANK_EINTG(5, 0x060, "gpc0"), + EXYNOS_PIN_BANK_EINTG(5, 0x080, "gpc1"), + EXYNOS_PIN_BANK_EINTG(4, 0x0A0, "gpd0"), + EXYNOS_PIN_BANK_EINTG(4, 0x0C0, "gpd1"), + EXYNOS_PIN_BANK_EINTG(5, 0x0E0, "gpe0"), + EXYNOS_PIN_BANK_EINTG(8, 0x100, "gpe1"), + EXYNOS_PIN_BANK_EINTG(6, 0x120, "gpe2"), + EXYNOS_PIN_BANK_EINTG(8, 0x140, "gpe3"), + EXYNOS_PIN_BANK_EINTG(8, 0x160, "gpe4"), + EXYNOS_PIN_BANK_EINTG(8, 0x180, "gpf0"), + EXYNOS_PIN_BANK_EINTG(8, 0x1A0, "gpf1"), + EXYNOS_PIN_BANK_EINTG(8, 0x1C0, "gpf2"), + EXYNOS_PIN_BANK_EINTG(6, 0x1E0, "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"), + EXYNOS_PIN_BANK_EINTG(8, 0x000, "gpj0"), + EXYNOS_PIN_BANK_EINTG(5, 0x020, "gpj1"), + EXYNOS_PIN_BANK_EINTG(7, 0x040, "gpk0"), + EXYNOS_PIN_BANK_EINTG(7, 0x060, "gpk1"), + EXYNOS_PIN_BANK_EINTG(7, 0x080, "gpk2"), + EXYNOS_PIN_BANK_EINTG(7, 0x0A0, "gpk3"), + EXYNOS_PIN_BANK_EINTG(8, 0x0C0, "gpl0"), + EXYNOS_PIN_BANK_EINTG(3, 0x0E0, "gpl1"), + EXYNOS_PIN_BANK_EINTG(8, 0x100, "gpl2"), + EXYNOS_PIN_BANK_EINTN(6, 0x120, "gpy0"), + EXYNOS_PIN_BANK_EINTN(4, 0x140, "gpy1"), + EXYNOS_PIN_BANK_EINTN(6, 0x160, "gpy2"), + EXYNOS_PIN_BANK_EINTN(8, 0x180, "gpy3"), + EXYNOS_PIN_BANK_EINTN(8, 0x1A0, "gpy4"), + EXYNOS_PIN_BANK_EINTN(8, 0x1C0, "gpy5"), + EXYNOS_PIN_BANK_EINTN(8, 0x1E0, "gpy6"), + EXYNOS_PIN_BANK_EINTN(8, 0xC00, "gpx0"), + EXYNOS_PIN_BANK_EINTN(8, 0xC20, "gpx1"), + EXYNOS_PIN_BANK_EINTN(8, 0xC40, "gpx2"), + EXYNOS_PIN_BANK_EINTN(8, 0xC60, "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"), + EXYNOS_PIN_BANK_EINTN(7, 0x000, "gpz"), }; /* @@ -540,9 +540,6 @@ 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, @@ -553,9 +550,6 @@ struct samsung_pin_ctrl exynos4210_pin_ctrl[] = { /* 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, @@ -571,9 +565,6 @@ struct samsung_pin_ctrl exynos4210_pin_ctrl[] = { /* 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", }, }; diff --git a/drivers/pinctrl/pinctrl-exynos.h b/drivers/pinctrl/pinctrl-exynos.h index 31d0a06174e..178846739e8 100644 --- a/drivers/pinctrl/pinctrl-exynos.h +++ b/drivers/pinctrl/pinctrl-exynos.h @@ -165,11 +165,10 @@ enum exynos4210_gpio_xc_start { #define EXYNOS_EINT_MAX_PER_BANK 8 #define EXYNOS_EINT_NR_WKUP_EINT -#define EXYNOS_PIN_BANK_EINTN(reg, __gpio, id) \ +#define EXYNOS_PIN_BANK_EINTN(pins, reg, id) \ { \ .pctl_offset = reg, \ - .pin_base = (__gpio##_START), \ - .nr_pins = (__gpio##_NR), \ + .nr_pins = pins, \ .func_width = 4, \ .pud_width = 2, \ .drv_width = 2, \ @@ -179,18 +178,16 @@ enum exynos4210_gpio_xc_start { .name = id \ } -#define EXYNOS_PIN_BANK_EINTG(reg, __gpio, id) \ +#define EXYNOS_PIN_BANK_EINTG(pins, reg, id) \ { \ .pctl_offset = reg, \ - .pin_base = (__gpio##_START), \ - .nr_pins = (__gpio##_NR), \ + .nr_pins = pins, \ .func_width = 4, \ .pud_width = 2, \ .drv_width = 2, \ .conpdn_width = 2, \ .pudpdn_width = 2, \ .eint_type = EINT_TYPE_GPIO, \ - .irq_base = (__gpio##_IRQ), \ .name = id \ } diff --git a/drivers/pinctrl/pinctrl-samsung.c b/drivers/pinctrl/pinctrl-samsung.c index aa42d54e89c..f219bb6779e 100644 --- a/drivers/pinctrl/pinctrl-samsung.c +++ b/drivers/pinctrl/pinctrl-samsung.c @@ -46,6 +46,8 @@ struct pin_config { { "samsung,pin-pud-pdn", PINCFG_TYPE_PUD_PDN }, }; +static unsigned int pin_base = 0; + /* check if the selector is a valid pin group selector */ static int samsung_get_group_count(struct pinctrl_dev *pctldev) { @@ -792,6 +794,9 @@ static struct samsung_pin_ctrl *samsung_pinctrl_get_soc_data( int id; const struct of_device_id *match; const struct device_node *node = pdev->dev.of_node; + struct samsung_pin_ctrl *ctrl; + struct samsung_pin_bank *bank; + int i; id = of_alias_get_id(pdev->dev.of_node, "pinctrl"); if (id < 0) { @@ -799,7 +804,22 @@ static struct samsung_pin_ctrl *samsung_pinctrl_get_soc_data( return NULL; } match = of_match_node(samsung_pinctrl_dt_match, node); - return (struct samsung_pin_ctrl *)match->data + id; + ctrl = (struct samsung_pin_ctrl *)match->data + id; + + bank = ctrl->pin_banks; + for (i = 0; i < ctrl->nr_banks; ++i, ++bank) { + bank->pin_base = ctrl->nr_pins; + ctrl->nr_pins += bank->nr_pins; + if (bank->eint_type == EINT_TYPE_GPIO) { + bank->irq_base = ctrl->nr_gint; + ctrl->nr_gint += bank->nr_pins; + } + } + + ctrl->base = pin_base; + pin_base += ctrl->nr_pins; + + return ctrl; } static int __devinit samsung_pinctrl_probe(struct platform_device *pdev) From 3a232ba86f3a93217ac717306645c5c555429858 Mon Sep 17 00:00:00 2001 From: Tomasz Figa Date: Thu, 11 Oct 2012 10:11:10 +0200 Subject: [PATCH 04/32] pinctrl: samsung: Remove static pin enumerations Since pin numbers are now assigned dynamically, those are not needed anymore. Signed-off-by: Tomasz Figa Reviewed-by: Kyungmin Park Acked-by: Thomas Abraham Signed-off-by: Linus Walleij --- drivers/pinctrl/pinctrl-exynos.h | 119 ------------------------------- 1 file changed, 119 deletions(-) diff --git a/drivers/pinctrl/pinctrl-exynos.h b/drivers/pinctrl/pinctrl-exynos.h index 178846739e8..2de4a2936e9 100644 --- a/drivers/pinctrl/pinctrl-exynos.h +++ b/drivers/pinctrl/pinctrl-exynos.h @@ -17,125 +17,6 @@ * (at your option) any later version. */ -#define EXYNOS_GPIO_START(__gpio) ((__gpio##_START) + (__gpio##_NR)) - -#define EXYNOS4210_GPIO_A0_NR (8) -#define EXYNOS4210_GPIO_A1_NR (6) -#define EXYNOS4210_GPIO_B_NR (8) -#define EXYNOS4210_GPIO_C0_NR (5) -#define EXYNOS4210_GPIO_C1_NR (5) -#define EXYNOS4210_GPIO_D0_NR (4) -#define EXYNOS4210_GPIO_D1_NR (4) -#define EXYNOS4210_GPIO_E0_NR (5) -#define EXYNOS4210_GPIO_E1_NR (8) -#define EXYNOS4210_GPIO_E2_NR (6) -#define EXYNOS4210_GPIO_E3_NR (8) -#define EXYNOS4210_GPIO_E4_NR (8) -#define EXYNOS4210_GPIO_F0_NR (8) -#define EXYNOS4210_GPIO_F1_NR (8) -#define EXYNOS4210_GPIO_F2_NR (8) -#define EXYNOS4210_GPIO_F3_NR (6) -#define EXYNOS4210_GPIO_J0_NR (8) -#define EXYNOS4210_GPIO_J1_NR (5) -#define EXYNOS4210_GPIO_K0_NR (7) -#define EXYNOS4210_GPIO_K1_NR (7) -#define EXYNOS4210_GPIO_K2_NR (7) -#define EXYNOS4210_GPIO_K3_NR (7) -#define EXYNOS4210_GPIO_L0_NR (8) -#define EXYNOS4210_GPIO_L1_NR (3) -#define EXYNOS4210_GPIO_L2_NR (8) -#define EXYNOS4210_GPIO_Y0_NR (6) -#define EXYNOS4210_GPIO_Y1_NR (4) -#define EXYNOS4210_GPIO_Y2_NR (6) -#define EXYNOS4210_GPIO_Y3_NR (8) -#define EXYNOS4210_GPIO_Y4_NR (8) -#define EXYNOS4210_GPIO_Y5_NR (8) -#define EXYNOS4210_GPIO_Y6_NR (8) -#define EXYNOS4210_GPIO_X0_NR (8) -#define EXYNOS4210_GPIO_X1_NR (8) -#define EXYNOS4210_GPIO_X2_NR (8) -#define EXYNOS4210_GPIO_X3_NR (8) -#define EXYNOS4210_GPIO_Z_NR (7) - -enum exynos4210_gpio_xa_start { - EXYNOS4210_GPIO_A0_START = 0, - EXYNOS4210_GPIO_A1_START = EXYNOS_GPIO_START(EXYNOS4210_GPIO_A0), - EXYNOS4210_GPIO_B_START = EXYNOS_GPIO_START(EXYNOS4210_GPIO_A1), - EXYNOS4210_GPIO_C0_START = EXYNOS_GPIO_START(EXYNOS4210_GPIO_B), - EXYNOS4210_GPIO_C1_START = EXYNOS_GPIO_START(EXYNOS4210_GPIO_C0), - EXYNOS4210_GPIO_D0_START = EXYNOS_GPIO_START(EXYNOS4210_GPIO_C1), - EXYNOS4210_GPIO_D1_START = EXYNOS_GPIO_START(EXYNOS4210_GPIO_D0), - EXYNOS4210_GPIO_E0_START = EXYNOS_GPIO_START(EXYNOS4210_GPIO_D1), - EXYNOS4210_GPIO_E1_START = EXYNOS_GPIO_START(EXYNOS4210_GPIO_E0), - EXYNOS4210_GPIO_E2_START = EXYNOS_GPIO_START(EXYNOS4210_GPIO_E1), - EXYNOS4210_GPIO_E3_START = EXYNOS_GPIO_START(EXYNOS4210_GPIO_E2), - EXYNOS4210_GPIO_E4_START = EXYNOS_GPIO_START(EXYNOS4210_GPIO_E3), - EXYNOS4210_GPIO_F0_START = EXYNOS_GPIO_START(EXYNOS4210_GPIO_E4), - EXYNOS4210_GPIO_F1_START = EXYNOS_GPIO_START(EXYNOS4210_GPIO_F0), - EXYNOS4210_GPIO_F2_START = EXYNOS_GPIO_START(EXYNOS4210_GPIO_F1), - EXYNOS4210_GPIO_F3_START = EXYNOS_GPIO_START(EXYNOS4210_GPIO_F2), -}; - -enum exynos4210_gpio_xb_start { - EXYNOS4210_GPIO_J0_START = 0, - EXYNOS4210_GPIO_J1_START = EXYNOS_GPIO_START(EXYNOS4210_GPIO_J0), - EXYNOS4210_GPIO_K0_START = EXYNOS_GPIO_START(EXYNOS4210_GPIO_J1), - EXYNOS4210_GPIO_K1_START = EXYNOS_GPIO_START(EXYNOS4210_GPIO_K0), - EXYNOS4210_GPIO_K2_START = EXYNOS_GPIO_START(EXYNOS4210_GPIO_K1), - EXYNOS4210_GPIO_K3_START = EXYNOS_GPIO_START(EXYNOS4210_GPIO_K2), - EXYNOS4210_GPIO_L0_START = EXYNOS_GPIO_START(EXYNOS4210_GPIO_K3), - EXYNOS4210_GPIO_L1_START = EXYNOS_GPIO_START(EXYNOS4210_GPIO_L0), - EXYNOS4210_GPIO_L2_START = EXYNOS_GPIO_START(EXYNOS4210_GPIO_L1), - EXYNOS4210_GPIO_Y0_START = EXYNOS_GPIO_START(EXYNOS4210_GPIO_L2), - EXYNOS4210_GPIO_Y1_START = EXYNOS_GPIO_START(EXYNOS4210_GPIO_Y0), - EXYNOS4210_GPIO_Y2_START = EXYNOS_GPIO_START(EXYNOS4210_GPIO_Y1), - EXYNOS4210_GPIO_Y3_START = EXYNOS_GPIO_START(EXYNOS4210_GPIO_Y2), - EXYNOS4210_GPIO_Y4_START = EXYNOS_GPIO_START(EXYNOS4210_GPIO_Y3), - EXYNOS4210_GPIO_Y5_START = EXYNOS_GPIO_START(EXYNOS4210_GPIO_Y4), - EXYNOS4210_GPIO_Y6_START = EXYNOS_GPIO_START(EXYNOS4210_GPIO_Y5), - EXYNOS4210_GPIO_X0_START = EXYNOS_GPIO_START(EXYNOS4210_GPIO_Y6), - EXYNOS4210_GPIO_X1_START = EXYNOS_GPIO_START(EXYNOS4210_GPIO_X0), - EXYNOS4210_GPIO_X2_START = EXYNOS_GPIO_START(EXYNOS4210_GPIO_X1), - EXYNOS4210_GPIO_X3_START = EXYNOS_GPIO_START(EXYNOS4210_GPIO_X2), -}; - -enum exynos4210_gpio_xc_start { - EXYNOS4210_GPIO_Z_START = 0, -}; - -#define EXYNOS4210_GPIO_A0_IRQ EXYNOS4210_GPIO_A0_START -#define EXYNOS4210_GPIO_A1_IRQ EXYNOS4210_GPIO_A1_START -#define EXYNOS4210_GPIO_B_IRQ EXYNOS4210_GPIO_B_START -#define EXYNOS4210_GPIO_C0_IRQ EXYNOS4210_GPIO_C0_START -#define EXYNOS4210_GPIO_C1_IRQ EXYNOS4210_GPIO_C1_START -#define EXYNOS4210_GPIO_D0_IRQ EXYNOS4210_GPIO_D0_START -#define EXYNOS4210_GPIO_D1_IRQ EXYNOS4210_GPIO_D1_START -#define EXYNOS4210_GPIO_E0_IRQ EXYNOS4210_GPIO_E0_START -#define EXYNOS4210_GPIO_E1_IRQ EXYNOS4210_GPIO_E1_START -#define EXYNOS4210_GPIO_E2_IRQ EXYNOS4210_GPIO_E2_START -#define EXYNOS4210_GPIO_E3_IRQ EXYNOS4210_GPIO_E3_START -#define EXYNOS4210_GPIO_E4_IRQ EXYNOS4210_GPIO_E4_START -#define EXYNOS4210_GPIO_F0_IRQ EXYNOS4210_GPIO_F0_START -#define EXYNOS4210_GPIO_F1_IRQ EXYNOS4210_GPIO_F1_START -#define EXYNOS4210_GPIO_F2_IRQ EXYNOS4210_GPIO_F2_START -#define EXYNOS4210_GPIO_F3_IRQ EXYNOS4210_GPIO_F3_START -#define EXYNOS4210_GPIO_J0_IRQ EXYNOS4210_GPIO_J0_START -#define EXYNOS4210_GPIO_J1_IRQ EXYNOS4210_GPIO_J1_START -#define EXYNOS4210_GPIO_K0_IRQ EXYNOS4210_GPIO_K0_START -#define EXYNOS4210_GPIO_K1_IRQ EXYNOS4210_GPIO_K1_START -#define EXYNOS4210_GPIO_K2_IRQ EXYNOS4210_GPIO_K2_START -#define EXYNOS4210_GPIO_K3_IRQ EXYNOS4210_GPIO_K3_START -#define EXYNOS4210_GPIO_L0_IRQ EXYNOS4210_GPIO_L0_START -#define EXYNOS4210_GPIO_L1_IRQ EXYNOS4210_GPIO_L1_START -#define EXYNOS4210_GPIO_L2_IRQ EXYNOS4210_GPIO_L2_START -#define EXYNOS4210_GPIO_Z_IRQ EXYNOS4210_GPIO_Z_START - -#define EXYNOS4210_GPIOA_NR_PINS EXYNOS_GPIO_START(EXYNOS4210_GPIO_F3) -#define EXYNOS4210_GPIOA_NR_GINT EXYNOS_GPIO_START(EXYNOS4210_GPIO_F3) -#define EXYNOS4210_GPIOB_NR_PINS EXYNOS_GPIO_START(EXYNOS4210_GPIO_X3) -#define EXYNOS4210_GPIOB_NR_GINT EXYNOS_GPIO_START(EXYNOS4210_GPIO_L2) -#define EXYNOS4210_GPIOC_NR_PINS EXYNOS_GPIO_START(EXYNOS4210_GPIO_Z) - /* External GPIO and wakeup interrupt related definitions */ #define EXYNOS_GPIO_ECON_OFFSET 0x700 #define EXYNOS_GPIO_EMASK_OFFSET 0x900 From 724e56a48c05dacc63ceb535571eec2ad6949368 Mon Sep 17 00:00:00 2001 From: Tomasz Figa Date: Thu, 11 Oct 2012 10:11:11 +0200 Subject: [PATCH 05/32] pinctrl: samsung: Distinguish between pin group and bank nodes This patch modifies the loop iterating over all child nodes and parsing pin groups to check whether the node is really a pin group node by checking for existence of samsung,pins property. This is a prerequisite for further patches adding additional subnodes to the pinctrl node, required for per bank GPIO and interrupt specifiers. Signed-off-by: Tomasz Figa Reviewed-by: Kyungmin Park Acked-by: Thomas Abraham Signed-off-by: Linus Walleij --- drivers/pinctrl/pinctrl-samsung.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/pinctrl/pinctrl-samsung.c b/drivers/pinctrl/pinctrl-samsung.c index f219bb6779e..94e13780a6a 100644 --- a/drivers/pinctrl/pinctrl-samsung.c +++ b/drivers/pinctrl/pinctrl-samsung.c @@ -609,7 +609,7 @@ 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)) + if (!of_find_property(cfg_np, "samsung,pins", NULL)) continue; ret = samsung_pinctrl_parse_dt_pins(pdev, cfg_np, From a7a8241540c3168965588d313f46b14f79e86753 Mon Sep 17 00:00:00 2001 From: Tomasz Figa Date: Thu, 11 Oct 2012 10:11:12 +0200 Subject: [PATCH 06/32] ARM: dts: exynos4210-pinctrl: Add nodes for pin banks This patch is a preparation for converting the pinctrl-samsung driver to one GPIO chip and IRQ domain per bank. It allows particular banks to be specified using their phandles. Signed-off-by: Tomasz Figa Reviewed-by: Kyungmin Park Acked-by: Thomas Abraham Signed-off-by: Linus Walleij --- arch/arm/boot/dts/exynos4210-pinctrl.dtsi | 272 ++++++++++++++++++++++ arch/arm/boot/dts/exynos4210.dtsi | 229 ------------------ 2 files changed, 272 insertions(+), 229 deletions(-) diff --git a/arch/arm/boot/dts/exynos4210-pinctrl.dtsi b/arch/arm/boot/dts/exynos4210-pinctrl.dtsi index b12cf272ad0..f207d8d6917 100644 --- a/arch/arm/boot/dts/exynos4210-pinctrl.dtsi +++ b/arch/arm/boot/dts/exynos4210-pinctrl.dtsi @@ -16,6 +16,134 @@ / { pinctrl@11400000 { + gpa0: gpa0 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpa1: gpa1 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpb: gpb { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpc0: gpc0 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpc1: gpc1 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpd0: gpd0 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpd1: gpd1 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpe0: gpe0 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpe1: gpe1 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpe2: gpe2 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpe3: gpe3 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpe4: gpe4 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpf0: gpf0 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpf1: gpf1 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpf2: gpf2 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpf3: gpf3 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + uart0_data: uart0-data { samsung,pins = "gpa0-0", "gpa0-1"; samsung,pin-function = <0x2>; @@ -205,6 +333,145 @@ }; pinctrl@11000000 { + gpj0: gpj0 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpj1: gpj1 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpk0: gpk0 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpk1: gpk1 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpk2: gpk2 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpk3: gpk3 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpl0: gpl0 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpl1: gpl1 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpl2: gpl2 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpy0: gpy0 { + gpio-controller; + #gpio-cells = <2>; + }; + + gpy1: gpy1 { + gpio-controller; + #gpio-cells = <2>; + }; + + gpy2: gpy2 { + gpio-controller; + #gpio-cells = <2>; + }; + + gpy3: gpy3 { + gpio-controller; + #gpio-cells = <2>; + }; + + gpy4: gpy4 { + gpio-controller; + #gpio-cells = <2>; + }; + + gpy5: gpy5 { + gpio-controller; + #gpio-cells = <2>; + }; + + gpy6: gpy6 { + gpio-controller; + #gpio-cells = <2>; + }; + + gpx0: gpx0 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpx1: gpx1 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpx2: gpx2 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpx3: gpx3 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + sd0_clk: sd0-clk { samsung,pins = "gpk0-0"; samsung,pin-function = <2>; @@ -438,6 +705,11 @@ }; pinctrl@03860000 { + gpz: gpz { + gpio-controller; + #gpio-cells = <2>; + }; + i2s0_bus: i2s0-bus { samsung,pins = "gpz-0", "gpz-1", "gpz-2", "gpz-3", "gpz-4", "gpz-5", "gpz-6"; diff --git a/arch/arm/boot/dts/exynos4210.dtsi b/arch/arm/boot/dts/exynos4210.dtsi index 214c557eda7..b768e9f4c58 100644 --- a/arch/arm/boot/dts/exynos4210.dtsi +++ b/arch/arm/boot/dts/exynos4210.dtsi @@ -74,233 +74,4 @@ compatible = "samsung,pinctrl-exynos4210"; reg = <0x03860000 0x1000>; }; - - gpio-controllers { - #address-cells = <1>; - #size-cells = <1>; - gpio-controller; - ranges; - - gpa0: gpio-controller@11400000 { - compatible = "samsung,exynos4-gpio"; - reg = <0x11400000 0x20>; - #gpio-cells = <4>; - }; - - gpa1: gpio-controller@11400020 { - compatible = "samsung,exynos4-gpio"; - reg = <0x11400020 0x20>; - #gpio-cells = <4>; - }; - - gpb: gpio-controller@11400040 { - compatible = "samsung,exynos4-gpio"; - reg = <0x11400040 0x20>; - #gpio-cells = <4>; - }; - - gpc0: gpio-controller@11400060 { - compatible = "samsung,exynos4-gpio"; - reg = <0x11400060 0x20>; - #gpio-cells = <4>; - }; - - gpc1: gpio-controller@11400080 { - compatible = "samsung,exynos4-gpio"; - reg = <0x11400080 0x20>; - #gpio-cells = <4>; - }; - - gpd0: gpio-controller@114000A0 { - compatible = "samsung,exynos4-gpio"; - reg = <0x114000A0 0x20>; - #gpio-cells = <4>; - }; - - gpd1: gpio-controller@114000C0 { - compatible = "samsung,exynos4-gpio"; - reg = <0x114000C0 0x20>; - #gpio-cells = <4>; - }; - - gpe0: gpio-controller@114000E0 { - compatible = "samsung,exynos4-gpio"; - reg = <0x114000E0 0x20>; - #gpio-cells = <4>; - }; - - gpe1: gpio-controller@11400100 { - compatible = "samsung,exynos4-gpio"; - reg = <0x11400100 0x20>; - #gpio-cells = <4>; - }; - - gpe2: gpio-controller@11400120 { - compatible = "samsung,exynos4-gpio"; - reg = <0x11400120 0x20>; - #gpio-cells = <4>; - }; - - gpe3: gpio-controller@11400140 { - compatible = "samsung,exynos4-gpio"; - reg = <0x11400140 0x20>; - #gpio-cells = <4>; - }; - - gpe4: gpio-controller@11400160 { - compatible = "samsung,exynos4-gpio"; - reg = <0x11400160 0x20>; - #gpio-cells = <4>; - }; - - gpf0: gpio-controller@11400180 { - compatible = "samsung,exynos4-gpio"; - reg = <0x11400180 0x20>; - #gpio-cells = <4>; - }; - - gpf1: gpio-controller@114001A0 { - compatible = "samsung,exynos4-gpio"; - reg = <0x114001A0 0x20>; - #gpio-cells = <4>; - }; - - gpf2: gpio-controller@114001C0 { - compatible = "samsung,exynos4-gpio"; - reg = <0x114001C0 0x20>; - #gpio-cells = <4>; - }; - - gpf3: gpio-controller@114001E0 { - compatible = "samsung,exynos4-gpio"; - reg = <0x114001E0 0x20>; - #gpio-cells = <4>; - }; - - gpj0: gpio-controller@11000000 { - compatible = "samsung,exynos4-gpio"; - reg = <0x11000000 0x20>; - #gpio-cells = <4>; - }; - - gpj1: gpio-controller@11000020 { - compatible = "samsung,exynos4-gpio"; - reg = <0x11000020 0x20>; - #gpio-cells = <4>; - }; - - gpk0: gpio-controller@11000040 { - compatible = "samsung,exynos4-gpio"; - reg = <0x11000040 0x20>; - #gpio-cells = <4>; - }; - - gpk1: gpio-controller@11000060 { - compatible = "samsung,exynos4-gpio"; - reg = <0x11000060 0x20>; - #gpio-cells = <4>; - }; - - gpk2: gpio-controller@11000080 { - compatible = "samsung,exynos4-gpio"; - reg = <0x11000080 0x20>; - #gpio-cells = <4>; - }; - - gpk3: gpio-controller@110000A0 { - compatible = "samsung,exynos4-gpio"; - reg = <0x110000A0 0x20>; - #gpio-cells = <4>; - }; - - gpl0: gpio-controller@110000C0 { - compatible = "samsung,exynos4-gpio"; - reg = <0x110000C0 0x20>; - #gpio-cells = <4>; - }; - - gpl1: gpio-controller@110000E0 { - compatible = "samsung,exynos4-gpio"; - reg = <0x110000E0 0x20>; - #gpio-cells = <4>; - }; - - gpl2: gpio-controller@11000100 { - compatible = "samsung,exynos4-gpio"; - reg = <0x11000100 0x20>; - #gpio-cells = <4>; - }; - - gpy0: gpio-controller@11000120 { - compatible = "samsung,exynos4-gpio"; - reg = <0x11000120 0x20>; - #gpio-cells = <4>; - }; - - gpy1: gpio-controller@11000140 { - compatible = "samsung,exynos4-gpio"; - reg = <0x11000140 0x20>; - #gpio-cells = <4>; - }; - - gpy2: gpio-controller@11000160 { - compatible = "samsung,exynos4-gpio"; - reg = <0x11000160 0x20>; - #gpio-cells = <4>; - }; - - gpy3: gpio-controller@11000180 { - compatible = "samsung,exynos4-gpio"; - reg = <0x11000180 0x20>; - #gpio-cells = <4>; - }; - - gpy4: gpio-controller@110001A0 { - compatible = "samsung,exynos4-gpio"; - reg = <0x110001A0 0x20>; - #gpio-cells = <4>; - }; - - gpy5: gpio-controller@110001C0 { - compatible = "samsung,exynos4-gpio"; - reg = <0x110001C0 0x20>; - #gpio-cells = <4>; - }; - - gpy6: gpio-controller@110001E0 { - compatible = "samsung,exynos4-gpio"; - reg = <0x110001E0 0x20>; - #gpio-cells = <4>; - }; - - gpx0: gpio-controller@11000C00 { - compatible = "samsung,exynos4-gpio"; - reg = <0x11000C00 0x20>; - #gpio-cells = <4>; - }; - - gpx1: gpio-controller@11000C20 { - compatible = "samsung,exynos4-gpio"; - reg = <0x11000C20 0x20>; - #gpio-cells = <4>; - }; - - gpx2: gpio-controller@11000C40 { - compatible = "samsung,exynos4-gpio"; - reg = <0x11000C40 0x20>; - #gpio-cells = <4>; - }; - - gpx3: gpio-controller@11000C60 { - compatible = "samsung,exynos4-gpio"; - reg = <0x11000C60 0x20>; - #gpio-cells = <4>; - }; - - gpz: gpio-controller@03860000 { - compatible = "samsung,exynos4-gpio"; - reg = <0x03860000 0x20>; - #gpio-cells = <4>; - }; - }; }; From ab663789d69760d2735402f66501f20b60312a3d Mon Sep 17 00:00:00 2001 From: Tomasz Figa Date: Thu, 11 Oct 2012 10:11:13 +0200 Subject: [PATCH 07/32] pinctrl: samsung: Match pin banks with their device nodes This patch is a preparation for converting the pinctrl-samsung driver to one GPIO chip and IRQ domain per bank. It binds banks defined by internal driver data with bank nodes in device tree. Signed-off-by: Tomasz Figa Reviewed-by: Kyungmin Park Acked-by: Thomas Abraham Signed-off-by: Linus Walleij --- drivers/pinctrl/pinctrl-samsung.c | 13 +++++++++++++ drivers/pinctrl/pinctrl-samsung.h | 2 ++ 2 files changed, 15 insertions(+) diff --git a/drivers/pinctrl/pinctrl-samsung.c b/drivers/pinctrl/pinctrl-samsung.c index 94e13780a6a..f266710a1b0 100644 --- a/drivers/pinctrl/pinctrl-samsung.c +++ b/drivers/pinctrl/pinctrl-samsung.c @@ -794,6 +794,7 @@ static struct samsung_pin_ctrl *samsung_pinctrl_get_soc_data( int id; const struct of_device_id *match; const struct device_node *node = pdev->dev.of_node; + struct device_node *np; struct samsung_pin_ctrl *ctrl; struct samsung_pin_bank *bank; int i; @@ -816,6 +817,18 @@ static struct samsung_pin_ctrl *samsung_pinctrl_get_soc_data( } } + for_each_child_of_node(node, np) { + if (!of_find_property(np, "gpio-controller", NULL)) + continue; + bank = ctrl->pin_banks; + for (i = 0; i < ctrl->nr_banks; ++i, ++bank) { + if (!strcmp(bank->name, np->name)) { + bank->of_node = np; + break; + } + } + } + ctrl->base = pin_base; pin_base += ctrl->nr_pins; diff --git a/drivers/pinctrl/pinctrl-samsung.h b/drivers/pinctrl/pinctrl-samsung.h index b8956934cda..5c53f32cca0 100644 --- a/drivers/pinctrl/pinctrl-samsung.h +++ b/drivers/pinctrl/pinctrl-samsung.h @@ -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: OF node of the bank. */ struct samsung_pin_bank { u32 pctl_offset; @@ -124,6 +125,7 @@ struct samsung_pin_bank { enum eint_type eint_type; u32 irq_base; char *name; + struct device_node *of_node; }; /** From 6defe9a0ddc59aa2302473aa3c8b3fdb543fdc1b Mon Sep 17 00:00:00 2001 From: Tomasz Figa Date: Thu, 11 Oct 2012 10:11:14 +0200 Subject: [PATCH 08/32] pinctrl: samsung: Hold pointer to driver data in bank struct This patch is a preparation for converting the pinctrl-samsung driver to one GPIO chip and IRQ domain per bank. It allows one having only a pointer to particular bank struct to access driver data struct. Signed-off-by: Tomasz Figa Reviewed-by: Kyungmin Park Acked-by: Thomas Abraham Signed-off-by: Linus Walleij --- drivers/pinctrl/pinctrl-samsung.c | 18 ++++++++++-------- drivers/pinctrl/pinctrl-samsung.h | 2 ++ 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/drivers/pinctrl/pinctrl-samsung.c b/drivers/pinctrl/pinctrl-samsung.c index f266710a1b0..53493c3c35f 100644 --- a/drivers/pinctrl/pinctrl-samsung.c +++ b/drivers/pinctrl/pinctrl-samsung.c @@ -789,17 +789,18 @@ static const struct of_device_id samsung_pinctrl_dt_match[]; /* retrieve the soc specific data */ static struct samsung_pin_ctrl *samsung_pinctrl_get_soc_data( + struct samsung_pinctrl_drv_data *d, struct platform_device *pdev) { 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 *np; struct samsung_pin_ctrl *ctrl; struct samsung_pin_bank *bank; int i; - 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; @@ -809,6 +810,7 @@ static struct samsung_pin_ctrl *samsung_pinctrl_get_soc_data( bank = ctrl->pin_banks; for (i = 0; i < ctrl->nr_banks; ++i, ++bank) { + bank->drvdata = d; bank->pin_base = ctrl->nr_pins; ctrl->nr_pins += bank->nr_pins; if (bank->eint_type == EINT_TYPE_GPIO) { @@ -848,18 +850,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(drvdata, pdev); + if (!ctrl) { + dev_err(&pdev->dev, "driver data not available\n"); + return -EINVAL; + } drvdata->ctrl = ctrl; drvdata->dev = dev; diff --git a/drivers/pinctrl/pinctrl-samsung.h b/drivers/pinctrl/pinctrl-samsung.h index 5c53f32cca0..ea5dadd3591 100644 --- a/drivers/pinctrl/pinctrl-samsung.h +++ b/drivers/pinctrl/pinctrl-samsung.h @@ -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: OF node of the bank. + * @drvdata: link to controller driver data */ struct samsung_pin_bank { u32 pctl_offset; @@ -126,6 +127,7 @@ struct samsung_pin_bank { u32 irq_base; char *name; struct device_node *of_node; + struct samsung_pinctrl_drv_data *drvdata; }; /** From 1b6056d6db2426cd612f03dabacf655ecb6a27ae Mon Sep 17 00:00:00 2001 From: Tomasz Figa Date: Thu, 11 Oct 2012 10:11:15 +0200 Subject: [PATCH 09/32] pinctrl: samsung: Include bank-specific eint offset in bank struct Some SoCs, like Exynos4x12, have non-sequential layout of EINT control registers and so current way of calculating register addresses does not work correctly for them. This patch adds eint_offset field to samsung_pin_bank struct and modifies the driver to use it instead of calculating the offsets from bank index. Signed-off-by: Tomasz Figa Reviewed-by: Kyungmin Park Acked-by: Thomas Abraham Signed-off-by: Linus Walleij --- drivers/pinctrl/pinctrl-exynos.c | 55 +++++++++++++++---------------- drivers/pinctrl/pinctrl-exynos.h | 3 +- drivers/pinctrl/pinctrl-samsung.h | 1 + 3 files changed, 30 insertions(+), 29 deletions(-) diff --git a/drivers/pinctrl/pinctrl-exynos.c b/drivers/pinctrl/pinctrl-exynos.c index 0ea2164bf6d..bd9f1307a79 100644 --- a/drivers/pinctrl/pinctrl-exynos.c +++ b/drivers/pinctrl/pinctrl-exynos.c @@ -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; } @@ -484,35 +483,35 @@ static int exynos_eint_wkup_init(struct samsung_pinctrl_drv_data *d) /* pin banks of exynos4210 pin-controller 0 */ static struct samsung_pin_bank exynos4210_pin_banks0[] = { - EXYNOS_PIN_BANK_EINTG(8, 0x000, "gpa0"), - EXYNOS_PIN_BANK_EINTG(6, 0x020, "gpa1"), - EXYNOS_PIN_BANK_EINTG(8, 0x040, "gpb"), - EXYNOS_PIN_BANK_EINTG(5, 0x060, "gpc0"), - EXYNOS_PIN_BANK_EINTG(5, 0x080, "gpc1"), - EXYNOS_PIN_BANK_EINTG(4, 0x0A0, "gpd0"), - EXYNOS_PIN_BANK_EINTG(4, 0x0C0, "gpd1"), - EXYNOS_PIN_BANK_EINTG(5, 0x0E0, "gpe0"), - EXYNOS_PIN_BANK_EINTG(8, 0x100, "gpe1"), - EXYNOS_PIN_BANK_EINTG(6, 0x120, "gpe2"), - EXYNOS_PIN_BANK_EINTG(8, 0x140, "gpe3"), - EXYNOS_PIN_BANK_EINTG(8, 0x160, "gpe4"), - EXYNOS_PIN_BANK_EINTG(8, 0x180, "gpf0"), - EXYNOS_PIN_BANK_EINTG(8, 0x1A0, "gpf1"), - EXYNOS_PIN_BANK_EINTG(8, 0x1C0, "gpf2"), - EXYNOS_PIN_BANK_EINTG(6, 0x1E0, "gpf3"), + EXYNOS_PIN_BANK_EINTG(8, 0x000, "gpa0", 0x00), + EXYNOS_PIN_BANK_EINTG(6, 0x020, "gpa1", 0x04), + EXYNOS_PIN_BANK_EINTG(8, 0x040, "gpb", 0x08), + EXYNOS_PIN_BANK_EINTG(5, 0x060, "gpc0", 0x0c), + EXYNOS_PIN_BANK_EINTG(5, 0x080, "gpc1", 0x10), + EXYNOS_PIN_BANK_EINTG(4, 0x0A0, "gpd0", 0x14), + EXYNOS_PIN_BANK_EINTG(4, 0x0C0, "gpd1", 0x18), + EXYNOS_PIN_BANK_EINTG(5, 0x0E0, "gpe0", 0x1c), + EXYNOS_PIN_BANK_EINTG(8, 0x100, "gpe1", 0x20), + EXYNOS_PIN_BANK_EINTG(6, 0x120, "gpe2", 0x24), + EXYNOS_PIN_BANK_EINTG(8, 0x140, "gpe3", 0x28), + EXYNOS_PIN_BANK_EINTG(8, 0x160, "gpe4", 0x2c), + EXYNOS_PIN_BANK_EINTG(8, 0x180, "gpf0", 0x30), + EXYNOS_PIN_BANK_EINTG(8, 0x1A0, "gpf1", 0x34), + EXYNOS_PIN_BANK_EINTG(8, 0x1C0, "gpf2", 0x38), + EXYNOS_PIN_BANK_EINTG(6, 0x1E0, "gpf3", 0x3c), }; /* pin banks of exynos4210 pin-controller 1 */ static struct samsung_pin_bank exynos4210_pin_banks1[] = { - EXYNOS_PIN_BANK_EINTG(8, 0x000, "gpj0"), - EXYNOS_PIN_BANK_EINTG(5, 0x020, "gpj1"), - EXYNOS_PIN_BANK_EINTG(7, 0x040, "gpk0"), - EXYNOS_PIN_BANK_EINTG(7, 0x060, "gpk1"), - EXYNOS_PIN_BANK_EINTG(7, 0x080, "gpk2"), - EXYNOS_PIN_BANK_EINTG(7, 0x0A0, "gpk3"), - EXYNOS_PIN_BANK_EINTG(8, 0x0C0, "gpl0"), - EXYNOS_PIN_BANK_EINTG(3, 0x0E0, "gpl1"), - EXYNOS_PIN_BANK_EINTG(8, 0x100, "gpl2"), + EXYNOS_PIN_BANK_EINTG(8, 0x000, "gpj0", 0x00), + EXYNOS_PIN_BANK_EINTG(5, 0x020, "gpj1", 0x04), + EXYNOS_PIN_BANK_EINTG(7, 0x040, "gpk0", 0x08), + EXYNOS_PIN_BANK_EINTG(7, 0x060, "gpk1", 0x0c), + EXYNOS_PIN_BANK_EINTG(7, 0x080, "gpk2", 0x10), + EXYNOS_PIN_BANK_EINTG(7, 0x0A0, "gpk3", 0x14), + EXYNOS_PIN_BANK_EINTG(8, 0x0C0, "gpl0", 0x18), + EXYNOS_PIN_BANK_EINTG(3, 0x0E0, "gpl1", 0x1c), + EXYNOS_PIN_BANK_EINTG(8, 0x100, "gpl2", 0x20), EXYNOS_PIN_BANK_EINTN(6, 0x120, "gpy0"), EXYNOS_PIN_BANK_EINTN(4, 0x140, "gpy1"), EXYNOS_PIN_BANK_EINTN(6, 0x160, "gpy2"), diff --git a/drivers/pinctrl/pinctrl-exynos.h b/drivers/pinctrl/pinctrl-exynos.h index 2de4a2936e9..5d8e380fbad 100644 --- a/drivers/pinctrl/pinctrl-exynos.h +++ b/drivers/pinctrl/pinctrl-exynos.h @@ -59,7 +59,7 @@ .name = id \ } -#define EXYNOS_PIN_BANK_EINTG(pins, reg, id) \ +#define EXYNOS_PIN_BANK_EINTG(pins, reg, id, offs) \ { \ .pctl_offset = reg, \ .nr_pins = pins, \ @@ -69,6 +69,7 @@ .conpdn_width = 2, \ .pudpdn_width = 2, \ .eint_type = EINT_TYPE_GPIO, \ + .eint_offset = offs, \ .name = id \ } diff --git a/drivers/pinctrl/pinctrl-samsung.h b/drivers/pinctrl/pinctrl-samsung.h index ea5dadd3591..d77d9bcc5d7 100644 --- a/drivers/pinctrl/pinctrl-samsung.h +++ b/drivers/pinctrl/pinctrl-samsung.h @@ -124,6 +124,7 @@ struct samsung_pin_bank { u8 conpdn_width; u8 pudpdn_width; enum eint_type eint_type; + u32 eint_offset; u32 irq_base; char *name; struct device_node *of_node; From 595be7268a85735d229451821b56f122d09d7bdc Mon Sep 17 00:00:00 2001 From: Tomasz Figa Date: Thu, 11 Oct 2012 10:11:16 +0200 Subject: [PATCH 10/32] pinctrl: exynos: Use one IRQ domain per pin bank 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>; /* ... */ }; Signed-off-by: Tomasz Figa Reviewed-by: Kyungmin Park Acked-by: Thomas Abraham Signed-off-by: Linus Walleij --- arch/arm/boot/dts/exynos4210.dtsi | 4 - drivers/pinctrl/pinctrl-exynos.c | 117 +++++++++--------------------- drivers/pinctrl/pinctrl-exynos.h | 12 --- drivers/pinctrl/pinctrl-samsung.c | 4 - drivers/pinctrl/pinctrl-samsung.h | 7 +- 5 files changed, 35 insertions(+), 109 deletions(-) diff --git a/arch/arm/boot/dts/exynos4210.dtsi b/arch/arm/boot/dts/exynos4210.dtsi index b768e9f4c58..c27aea73abf 100644 --- a/arch/arm/boot/dts/exynos4210.dtsi +++ b/arch/arm/boot/dts/exynos4210.dtsi @@ -46,16 +46,12 @@ compatible = "samsung,pinctrl-exynos4210"; reg = <0x11400000 0x1000>; interrupts = <0 47 0>; - interrupt-controller; - #interrupt-cells = <2>; }; pinctrl_1: pinctrl@11000000 { compatible = "samsung,pinctrl-exynos4210"; reg = <0x11000000 0x1000>; interrupts = <0 46 0>; - interrupt-controller; - #interrupt-cells = <2>; wakup_eint: wakeup-interrupt-controller { compatible = "samsung,exynos4210-wakeup-eint"; diff --git a/drivers/pinctrl/pinctrl-exynos.c b/drivers/pinctrl/pinctrl-exynos.c index bd9f1307a79..be757b1d4fc 100644 --- a/drivers/pinctrl/pinctrl-exynos.c +++ b/drivers/pinctrl/pinctrl-exynos.c @@ -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; + 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_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; diff --git a/drivers/pinctrl/pinctrl-exynos.h b/drivers/pinctrl/pinctrl-exynos.h index 5d8e380fbad..f05efa07465 100644 --- a/drivers/pinctrl/pinctrl-exynos.h +++ b/drivers/pinctrl/pinctrl-exynos.h @@ -73,18 +73,6 @@ .name = id \ } -/** - * 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. diff --git a/drivers/pinctrl/pinctrl-samsung.c b/drivers/pinctrl/pinctrl-samsung.c index 53493c3c35f..e1ef5d28094 100644 --- a/drivers/pinctrl/pinctrl-samsung.c +++ b/drivers/pinctrl/pinctrl-samsung.c @@ -813,10 +813,6 @@ static struct samsung_pin_ctrl *samsung_pinctrl_get_soc_data( bank->drvdata = d; bank->pin_base = ctrl->nr_pins; ctrl->nr_pins += bank->nr_pins; - if (bank->eint_type == EINT_TYPE_GPIO) { - bank->irq_base = ctrl->nr_gint; - ctrl->nr_gint += bank->nr_pins; - } } for_each_child_of_node(node, np) { diff --git a/drivers/pinctrl/pinctrl-samsung.h b/drivers/pinctrl/pinctrl-samsung.h index d77d9bcc5d7..e56be22302c 100644 --- a/drivers/pinctrl/pinctrl-samsung.h +++ b/drivers/pinctrl/pinctrl-samsung.h @@ -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: OF node of the bank. * @drvdata: link to controller driver data + * @irq_domain: IRQ domain of the bank. */ struct samsung_pin_bank { u32 pctl_offset; @@ -125,10 +125,10 @@ struct samsung_pin_bank { u8 pudpdn_width; enum eint_type eint_type; u32 eint_offset; - u32 irq_base; char *name; struct device_node *of_node; struct samsung_pinctrl_drv_data *drvdata; + struct irq_domain *irq_domain; }; /** @@ -137,7 +137,6 @@ struct samsung_pin_bank { * @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. @@ -158,7 +157,6 @@ struct samsung_pin_ctrl { u32 base; u32 nr_pins; - u32 nr_gint; u32 nr_wint; u32 geint_con; @@ -205,7 +203,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; From d3a7b9e3a168df881a0ae3bd0d582f44a5d5aca3 Mon Sep 17 00:00:00 2001 From: Tomasz Figa Date: Thu, 11 Oct 2012 10:11:17 +0200 Subject: [PATCH 11/32] pinctrl: samsung: Use one GPIO chip per pin bank 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>; /* ... */ }; Signed-off-by: Tomasz Figa Reviewed-by: Kyungmin Park Acked-by: Thomas Abraham Signed-off-by: Linus Walleij --- drivers/pinctrl/pinctrl-samsung.c | 115 +++++++++++++++++++----------- drivers/pinctrl/pinctrl-samsung.h | 11 +-- 2 files changed, 78 insertions(+), 48 deletions(-) diff --git a/drivers/pinctrl/pinctrl-samsung.c b/drivers/pinctrl/pinctrl-samsung.c index e1ef5d28094..0a38368edcd 100644 --- a/drivers/pinctrl/pinctrl-samsung.c +++ b/drivers/pinctrl/pinctrl-samsung.c @@ -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; } @@ -724,12 +730,16 @@ 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.pin_base = pin_bank->pin_base; + 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) { @@ -740,49 +750,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; + int i; - gc = devm_kzalloc(&pdev->dev, sizeof(*gc), GFP_KERNEL); - if (!gc) { - dev_err(&pdev->dev, "mem alloc for gpio_chip failed\n"); - return -ENOMEM; - } + for (i = 0; i < ctrl->nr_banks; ++i, ++bank) { + bank->gpio_chip = samsung_gpiolib_chip; - 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; + 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[]; diff --git a/drivers/pinctrl/pinctrl-samsung.h b/drivers/pinctrl/pinctrl-samsung.h index e56be22302c..dac40ffd5e6 100644 --- a/drivers/pinctrl/pinctrl-samsung.h +++ b/drivers/pinctrl/pinctrl-samsung.h @@ -23,6 +23,8 @@ #include #include +#include + /* 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: OF node of the bank. * @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; @@ -129,6 +133,8 @@ 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; }; /** @@ -186,8 +192,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; @@ -204,9 +208,6 @@ struct samsung_pinctrl_drv_data { unsigned int nr_functions; struct irq_domain *wkup_irqd; - - struct gpio_chip *gc; - struct pinctrl_gpio_range grange; }; /** From a04b07c0fc4d63e3fb9fea84d48a177ac5bd9164 Mon Sep 17 00:00:00 2001 From: Tomasz Figa Date: Thu, 11 Oct 2012 10:11:18 +0200 Subject: [PATCH 12/32] pinctrl: samsung: Use per-bank IRQ domain for wake-up interrupts This 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 code anymore, but defined in SoC-specific structure - 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 Signed-off-by: Tomasz Figa Reviewed-by: Kyungmin Park Acked-by: Thomas Abraham Signed-off-by: Linus Walleij --- arch/arm/boot/dts/exynos4210-pinctrl.dtsi | 6 + arch/arm/boot/dts/exynos4210.dtsi | 8 +- drivers/pinctrl/pinctrl-exynos.c | 163 ++++++++++++++-------- drivers/pinctrl/pinctrl-exynos.h | 29 +++- drivers/pinctrl/pinctrl-samsung.h | 6 +- 5 files changed, 136 insertions(+), 76 deletions(-) diff --git a/arch/arm/boot/dts/exynos4210-pinctrl.dtsi b/arch/arm/boot/dts/exynos4210-pinctrl.dtsi index f207d8d6917..6a4a1a04221 100644 --- a/arch/arm/boot/dts/exynos4210-pinctrl.dtsi +++ b/arch/arm/boot/dts/exynos4210-pinctrl.dtsi @@ -445,6 +445,9 @@ #gpio-cells = <2>; interrupt-controller; + 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>; #interrupt-cells = <2>; }; @@ -453,6 +456,9 @@ #gpio-cells = <2>; interrupt-controller; + 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>; #interrupt-cells = <2>; }; diff --git a/arch/arm/boot/dts/exynos4210.dtsi b/arch/arm/boot/dts/exynos4210.dtsi index c27aea73abf..d877dbe7ac0 100644 --- a/arch/arm/boot/dts/exynos4210.dtsi +++ b/arch/arm/boot/dts/exynos4210.dtsi @@ -56,13 +56,7 @@ wakup_eint: 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>; }; }; diff --git a/drivers/pinctrl/pinctrl-exynos.c b/drivers/pinctrl/pinctrl-exynos.c index be757b1d4fc..4bf2fc40aca 100644 --- a/drivers/pinctrl/pinctrl-exynos.c +++ b/drivers/pinctrl/pinctrl-exynos.c @@ -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; for_each_child_of_node(dev->of_node, np) { @@ -393,40 +399,74 @@ static int exynos_eint_wkup_init(struct samsung_pinctrl_drv_data *d) if (!wkup_np) return -ENODEV; - 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[idx]); + 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"); + 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; + } + + 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; } - 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"); - } + irq_set_chained_handler(irq, exynos_irq_demux_eint16_31); + irq_set_handler_data(irq, muxed_data); - for (idx = 0; idx < 16; idx++) { - weint_data[idx].domain = d->wkup_irqd; - weint_data[idx].irq = 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; - 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); - } + muxed_data->banks[idx++] = bank; } + muxed_data->nr_banks = muxed_banks; + return 0; } @@ -468,10 +508,10 @@ static struct samsung_pin_bank exynos4210_pin_banks1[] = { EXYNOS_PIN_BANK_EINTN(8, 0x1A0, "gpy4"), EXYNOS_PIN_BANK_EINTN(8, 0x1C0, "gpy5"), EXYNOS_PIN_BANK_EINTN(8, 0x1E0, "gpy6"), - EXYNOS_PIN_BANK_EINTN(8, 0xC00, "gpx0"), - EXYNOS_PIN_BANK_EINTN(8, 0xC20, "gpx1"), - EXYNOS_PIN_BANK_EINTN(8, 0xC40, "gpx2"), - EXYNOS_PIN_BANK_EINTN(8, 0xC60, "gpx3"), + EXYNOS_PIN_BANK_EINTW(8, 0xC00, "gpx0", 0x00), + EXYNOS_PIN_BANK_EINTW(8, 0xC20, "gpx1", 0x04), + EXYNOS_PIN_BANK_EINTW(8, 0xC40, "gpx2", 0x08), + EXYNOS_PIN_BANK_EINTW(8, 0xC60, "gpx3", 0x0c), }; /* pin banks of exynos4210 pin-controller 2 */ @@ -498,7 +538,6 @@ struct samsung_pin_ctrl exynos4210_pin_ctrl[] = { /* pin-controller instance 1 data */ .pin_banks = exynos4210_pin_banks1, .nr_banks = ARRAY_SIZE(exynos4210_pin_banks1), - .nr_wint = 32, .geint_con = EXYNOS_GPIO_ECON_OFFSET, .geint_mask = EXYNOS_GPIO_EMASK_OFFSET, .geint_pend = EXYNOS_GPIO_EPEND_OFFSET, diff --git a/drivers/pinctrl/pinctrl-exynos.h b/drivers/pinctrl/pinctrl-exynos.h index f05efa07465..0a708890d8b 100644 --- a/drivers/pinctrl/pinctrl-exynos.h +++ b/drivers/pinctrl/pinctrl-exynos.h @@ -73,13 +73,36 @@ .name = id \ } +#define EXYNOS_PIN_BANK_EINTW(pins, reg, id, offs) \ + { \ + .pctl_offset = reg, \ + .nr_pins = pins, \ + .func_width = 4, \ + .pud_width = 2, \ + .drv_width = 2, \ + .eint_type = EINT_TYPE_WKUP, \ + .eint_offset = offs, \ + .name = id \ + } + /** * 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[]; }; diff --git a/drivers/pinctrl/pinctrl-samsung.h b/drivers/pinctrl/pinctrl-samsung.h index dac40ffd5e6..0670d9ea43f 100644 --- a/drivers/pinctrl/pinctrl-samsung.h +++ b/drivers/pinctrl/pinctrl-samsung.h @@ -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") */ @@ -143,7 +145,6 @@ struct samsung_pin_bank { * @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. @@ -163,7 +164,6 @@ struct samsung_pin_ctrl { u32 base; u32 nr_pins; - u32 nr_wint; u32 geint_con; u32 geint_mask; @@ -206,8 +206,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; }; /** From 22b9ba033bb4401e4cceb69c9e1af74a4631dd74 Mon Sep 17 00:00:00 2001 From: Tomasz Figa Date: Thu, 11 Oct 2012 10:11:19 +0200 Subject: [PATCH 13/32] pinctrl: exynos: Set pin function to EINT in irq_set_type of wake-up EINT Pins 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. Signed-off-by: Tomasz Figa Reviewed-by: Kyungmin Park Acked-by: Thomas Abraham Signed-off-by: Linus Walleij --- drivers/pinctrl/pinctrl-exynos.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/drivers/pinctrl/pinctrl-exynos.c b/drivers/pinctrl/pinctrl-exynos.c index 4bf2fc40aca..73a0aa27cd5 100644 --- a/drivers/pinctrl/pinctrl-exynos.c +++ b/drivers/pinctrl/pinctrl-exynos.c @@ -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; } From a19fe2d45cc550ca42a3b0be3e716a8452e4b0c6 Mon Sep 17 00:00:00 2001 From: Tomasz Figa Date: Thu, 11 Oct 2012 10:11:20 +0200 Subject: [PATCH 14/32] pinctrl: samsung: Add GPIO to IRQ translation Some drivers require a way to translate GPIO pins to their IRQ numbers. This patch adds the .to_irq() gpiolib callback to pinctrl-samsung driver, which creates (if not present yet) and returns an IRQ mapping for given GPIO pin. Signed-off-by: Tomasz Figa Reviewed-by: Kyungmin Park Acked-by: Thomas Abraham Signed-off-by: Linus Walleij --- drivers/pinctrl/pinctrl-samsung.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/drivers/pinctrl/pinctrl-samsung.c b/drivers/pinctrl/pinctrl-samsung.c index 0a38368edcd..0db88bbbb2b 100644 --- a/drivers/pinctrl/pinctrl-samsung.c +++ b/drivers/pinctrl/pinctrl-samsung.c @@ -26,6 +26,7 @@ #include #include #include +#include #include "core.h" #include "pinctrl-samsung.h" @@ -527,6 +528,23 @@ static int samsung_gpio_direction_output(struct gpio_chip *gc, unsigned offset, return pinctrl_gpio_direction_output(gc->base + offset); } +/* + * gpiolib gpio_to_irq callback function. Creates a mapping between a GPIO pin + * and a virtual IRQ, if not already present. + */ +static int samsung_gpio_to_irq(struct gpio_chip *gc, unsigned offset) +{ + struct samsung_pin_bank *bank = gc_to_pin_bank(gc); + unsigned int virq; + + if (!bank->irq_domain) + return -ENXIO; + + virq = irq_create_mapping(bank->irq_domain, offset); + + return (virq) ? : -ENXIO; +} + /* * Parse the pin names listed in the 'samsung,pins' property and convert it * into a list of gpio numbers are create a pin group from it. @@ -755,6 +773,7 @@ static const struct gpio_chip samsung_gpiolib_chip = { .get = samsung_gpio_get, .direction_input = samsung_gpio_direction_input, .direction_output = samsung_gpio_direction_output, + .to_irq = samsung_gpio_to_irq, .owner = THIS_MODULE, }; From b33ef91f4b799a5de5904c4b361df97a0c3ec7dd Mon Sep 17 00:00:00 2001 From: Tomasz Figa Date: Thu, 11 Oct 2012 10:11:21 +0200 Subject: [PATCH 15/32] Documentation: Update samsung-pinctrl device tree bindings documentation Signed-off-by: Tomasz Figa Reviewed-by: Kyungmin Park Acked-by: Thomas Abraham Signed-off-by: Linus Walleij --- .../bindings/pinctrl/samsung-pinctrl.txt | 118 ++++++++++++++---- 1 file changed, 93 insertions(+), 25 deletions(-) diff --git a/Documentation/devicetree/bindings/pinctrl/samsung-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/samsung-pinctrl.txt index 03dee50532f..63806e2d49c 100644 --- a/Documentation/devicetree/bindings/pinctrl/samsung-pinctrl.txt +++ b/Documentation/devicetree/bindings/pinctrl/samsung-pinctrl.txt @@ -13,8 +13,14 @@ 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 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. + - #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 +78,24 @@ 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 + - 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. + - #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,6 +108,11 @@ 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. + + 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. - #interrupt-cells: the value of this property should be 2 - First Cell: represents the external wakeup interrupt number local to @@ -105,11 +124,63 @@ 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: A pin-controller node with pin banks: + + pinctrl_0: pinctrl@11400000 { + compatible = "samsung,pinctrl-exynos4210"; + reg = <0x11400000 0x1000>; + interrupts = <0 47 0>; + + /* ... */ + + /* Pin bank without external interrupts */ + gpy0: gpy0 { + gpio-controller; + #gpio-cells = <2>; + }; + + /* ... */ + + /* Pin bank with external GPIO or muxed wake-up interrupts */ + gpj0: gpj0 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + /* ... */ + + /* Pin bank with external direct wake-up interrupts */ + gpx0: gpx0 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + 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>; + #interrupt-cells = <2>; + }; + + /* ... */ + }; + Example 1: A pin-controller node with pin groups. pinctrl_0: pinctrl@11400000 { @@ -117,6 +188,8 @@ Example 1: A pin-controller node with pin groups. reg = <0x11400000 0x1000>; interrupts = <0 47 0>; + /* ... */ + uart0_data: uart0-data { samsung,pins = "gpa0-0", "gpa0-1"; samsung,pin-function = <2>; @@ -158,20 +231,14 @@ Example 2: A pin-controller node with external wakeup interrupt controller node. pinctrl_1: pinctrl@11000000 { compatible = "samsung,pinctrl-exynos4210"; reg = <0x11000000 0x1000>; - interrupts = <0 46 0>; - interrupt-controller; - #interrupt-cells = <2>; + interrupts = <0 46 0> - 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>; }; }; @@ -190,7 +257,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); } From 70191db9308e33b5d0063f3a4a6ad22abf594a9d Mon Sep 17 00:00:00 2001 From: Tomasz Figa Date: Wed, 17 Oct 2012 18:13:24 +0900 Subject: [PATCH 16/32] ARM: dts: Enable serial controllers on Origen and SMDKV310 This patch adds status override of serial nodes to enable used serial ports on Origen and SMDKV310 board. Signed-off-by: Tomasz Figa Signed-off-by: Kukjin Kim --- arch/arm/boot/dts/exynos4210-origen.dts | 16 ++++++++++++++++ arch/arm/boot/dts/exynos4210-smdkv310.dts | 16 ++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/arch/arm/boot/dts/exynos4210-origen.dts b/arch/arm/boot/dts/exynos4210-origen.dts index 3e68f52e845..f16c99f2f0f 100644 --- a/arch/arm/boot/dts/exynos4210-origen.dts +++ b/arch/arm/boot/dts/exynos4210-origen.dts @@ -57,6 +57,22 @@ status = "okay"; }; + serial@13800000 { + status = "okay"; + }; + + serial@13810000 { + status = "okay"; + }; + + serial@13820000 { + status = "okay"; + }; + + serial@13830000 { + status = "okay"; + }; + gpio_keys { compatible = "gpio-keys"; #address-cells = <1>; diff --git a/arch/arm/boot/dts/exynos4210-smdkv310.dts b/arch/arm/boot/dts/exynos4210-smdkv310.dts index 63610c3ba3a..9b23a8255e3 100644 --- a/arch/arm/boot/dts/exynos4210-smdkv310.dts +++ b/arch/arm/boot/dts/exynos4210-smdkv310.dts @@ -43,6 +43,22 @@ status = "okay"; }; + serial@13800000 { + status = "okay"; + }; + + serial@13810000 { + status = "okay"; + }; + + serial@13820000 { + status = "okay"; + }; + + serial@13830000 { + status = "okay"; + }; + keypad@100A0000 { samsung,keypad-num-rows = <2>; samsung,keypad-num-columns = <8>; From 2eae613b95a786714bd1b5825ea3abc78d229d3f Mon Sep 17 00:00:00 2001 From: Arun Kumar K Date: Tue, 23 Oct 2012 22:51:33 +0900 Subject: [PATCH 17/32] ARM: EXYNOS: Add MFC device tree support This patch adds device tree entry for MFC v6 in the Exynos5 SoC. Makes the required changes in the clock files and adds MFC to the DT device list. Signed-off-by: Naveen Krishna Chatradhi Signed-off-by: Arun Kumar K [kgene.kim@samsung.com: fixed section mismatches Seung-Woo Kim reported] Signed-off-by: Kukjin Kim --- .../devicetree/bindings/media/s5p-mfc.txt | 23 +++++++++++++ arch/arm/boot/dts/exynos5250-smdk5250.dts | 5 +++ arch/arm/boot/dts/exynos5250.dtsi | 6 ++++ arch/arm/mach-exynos/Kconfig | 1 + arch/arm/mach-exynos/clock-exynos5.c | 2 +- arch/arm/mach-exynos/mach-exynos5-dt.c | 16 +++++++++ arch/arm/plat-samsung/devs.c | 1 + arch/arm/plat-samsung/include/plat/mfc.h | 11 ++++++ arch/arm/plat-samsung/s5p-dev-mfc.c | 34 +++++++++++++++++++ 9 files changed, 98 insertions(+), 1 deletion(-) create mode 100644 Documentation/devicetree/bindings/media/s5p-mfc.txt diff --git a/Documentation/devicetree/bindings/media/s5p-mfc.txt b/Documentation/devicetree/bindings/media/s5p-mfc.txt new file mode 100644 index 00000000000..67ec3d4ccc7 --- /dev/null +++ b/Documentation/devicetree/bindings/media/s5p-mfc.txt @@ -0,0 +1,23 @@ +* Samsung Multi Format Codec (MFC) + +Multi Format Codec (MFC) is the IP present in Samsung SoCs which +supports high resolution decoding and encoding functionalities. +The MFC device driver is a v4l2 driver which can encode/decode +video raw/elementary streams and has support for all popular +video codecs. + +Required properties: + - compatible : value should be either one among the following + (a) "samsung,mfc-v5" for MFC v5 present in Exynos4 SoCs + (b) "samsung,mfc-v6" for MFC v6 present in Exynos5 SoCs + + - reg : Physical base address of the IP registers and length of memory + mapped region. + + - interrupts : MFC interrupt number to the CPU. + + - samsung,mfc-r : Base address of the first memory bank used by MFC + for DMA contiguous memory allocation and its size. + + - samsung,mfc-l : Base address of the second memory bank used by MFC + for DMA contiguous memory allocation and its size. diff --git a/arch/arm/boot/dts/exynos5250-smdk5250.dts b/arch/arm/boot/dts/exynos5250-smdk5250.dts index a352df403b7..21d4ccdb0a5 100644 --- a/arch/arm/boot/dts/exynos5250-smdk5250.dts +++ b/arch/arm/boot/dts/exynos5250-smdk5250.dts @@ -166,4 +166,9 @@ spi_2: spi@12d40000 { status = "disabled"; }; + + codec@11000000 { + samsung,mfc-r = <0x43000000 0x800000>; + samsung,mfc-l = <0x51000000 0x800000>; + }; }; diff --git a/arch/arm/boot/dts/exynos5250.dtsi b/arch/arm/boot/dts/exynos5250.dtsi index dddfd6e444d..49546bc43ec 100644 --- a/arch/arm/boot/dts/exynos5250.dtsi +++ b/arch/arm/boot/dts/exynos5250.dtsi @@ -62,6 +62,12 @@ interrupts = <0 42 0>; }; + codec@11000000 { + compatible = "samsung,mfc-v6"; + reg = <0x11000000 0x10000>; + interrupts = <0 96 0>; + }; + rtc { compatible = "samsung,s3c6410-rtc"; reg = <0x101E0000 0x100>; diff --git a/arch/arm/mach-exynos/Kconfig b/arch/arm/mach-exynos/Kconfig index da55107033d..bb3b09aa918 100644 --- a/arch/arm/mach-exynos/Kconfig +++ b/arch/arm/mach-exynos/Kconfig @@ -63,6 +63,7 @@ config SOC_EXYNOS5250 depends on ARCH_EXYNOS5 select S5P_PM if PM select S5P_SLEEP if PM + select S5P_DEV_MFC select SAMSUNG_DMADEV help Enable EXYNOS5250 SoC support diff --git a/arch/arm/mach-exynos/clock-exynos5.c b/arch/arm/mach-exynos/clock-exynos5.c index c44ca1ee1b8..8c4e3253cdb 100644 --- a/arch/arm/mach-exynos/clock-exynos5.c +++ b/arch/arm/mach-exynos/clock-exynos5.c @@ -664,7 +664,7 @@ static struct clk exynos5_init_clocks_off[] = { .ctrlbit = (1 << 25), }, { .name = "mfc", - .devname = "s5p-mfc", + .devname = "s5p-mfc-v6", .enable = exynos5_clk_ip_mfc_ctrl, .ctrlbit = (1 << 0), }, { diff --git a/arch/arm/mach-exynos/mach-exynos5-dt.c b/arch/arm/mach-exynos/mach-exynos5-dt.c index db1cd8eacf2..b7f1154088b 100644 --- a/arch/arm/mach-exynos/mach-exynos5-dt.c +++ b/arch/arm/mach-exynos/mach-exynos5-dt.c @@ -11,6 +11,8 @@ #include #include +#include +#include #include #include @@ -18,6 +20,7 @@ #include #include +#include #include "common.h" @@ -72,6 +75,7 @@ static const struct of_dev_auxdata exynos5250_auxdata_lookup[] __initconst = { "exynos-gsc.2", NULL), OF_DEV_AUXDATA("samsung,exynos5-gsc", EXYNOS5_PA_GSC3, "exynos-gsc.3", NULL), + OF_DEV_AUXDATA("samsung,mfc-v6", 0x11000000, "s5p-mfc-v6", NULL), {}, }; @@ -92,6 +96,17 @@ static char const *exynos5250_dt_compat[] __initdata = { NULL }; +static void __init exynos5_reserve(void) +{ + struct s5p_mfc_dt_meminfo mfc_mem; + + /* Reserve memory for MFC only if it's available */ + mfc_mem.compatible = "samsung,mfc-v6"; + if (of_scan_flat_dt(s5p_fdt_find_mfc_mem, &mfc_mem)) + s5p_mfc_reserve_mem(mfc_mem.roff, mfc_mem.rsize, mfc_mem.loff, + mfc_mem.lsize); +} + DT_MACHINE_START(EXYNOS5_DT, "SAMSUNG EXYNOS5 (Flattened Device Tree)") /* Maintainer: Kukjin Kim */ .init_irq = exynos5_init_irq, @@ -103,4 +118,5 @@ DT_MACHINE_START(EXYNOS5_DT, "SAMSUNG EXYNOS5 (Flattened Device Tree)") .timer = &exynos4_timer, .dt_compat = exynos5250_dt_compat, .restart = exynos5_restart, + .reserve = exynos5_reserve, MACHINE_END diff --git a/arch/arm/plat-samsung/devs.c b/arch/arm/plat-samsung/devs.c index 03f654d55ef..52dfa8f914c 100644 --- a/arch/arm/plat-samsung/devs.c +++ b/arch/arm/plat-samsung/devs.c @@ -933,6 +933,7 @@ struct platform_device s5p_device_mfc_r = { .coherent_dma_mask = DMA_BIT_MASK(32), }, }; + #endif /* CONFIG_S5P_DEV_MFC */ /* MIPI CSIS */ diff --git a/arch/arm/plat-samsung/include/plat/mfc.h b/arch/arm/plat-samsung/include/plat/mfc.h index ac13227272f..e6d7c42d68b 100644 --- a/arch/arm/plat-samsung/include/plat/mfc.h +++ b/arch/arm/plat-samsung/include/plat/mfc.h @@ -10,6 +10,14 @@ #ifndef __PLAT_SAMSUNG_MFC_H #define __PLAT_SAMSUNG_MFC_H __FILE__ +struct s5p_mfc_dt_meminfo { + unsigned long loff; + unsigned long lsize; + unsigned long roff; + unsigned long rsize; + char *compatible; +}; + /** * s5p_mfc_reserve_mem - function to early reserve memory for MFC driver * @rbase: base address for MFC 'right' memory interface @@ -24,4 +32,7 @@ void __init s5p_mfc_reserve_mem(phys_addr_t rbase, unsigned int rsize, phys_addr_t lbase, unsigned int lsize); +int __init s5p_fdt_find_mfc_mem(unsigned long node, const char *uname, + int depth, void *data); + #endif /* __PLAT_SAMSUNG_MFC_H */ diff --git a/arch/arm/plat-samsung/s5p-dev-mfc.c b/arch/arm/plat-samsung/s5p-dev-mfc.c index ad6089465e2..5ec104b5408 100644 --- a/arch/arm/plat-samsung/s5p-dev-mfc.c +++ b/arch/arm/plat-samsung/s5p-dev-mfc.c @@ -14,6 +14,8 @@ #include #include #include +#include +#include #include #include @@ -69,3 +71,35 @@ static int __init s5p_mfc_memory_init(void) return 0; } device_initcall(s5p_mfc_memory_init); + +#ifdef CONFIG_OF +int __init s5p_fdt_find_mfc_mem(unsigned long node, const char *uname, + int depth, void *data) +{ + __be32 *prop; + unsigned long len; + struct s5p_mfc_dt_meminfo *mfc_mem = data; + + if (!data) + return 0; + + if (!of_flat_dt_is_compatible(node, mfc_mem->compatible)) + return 0; + + prop = of_get_flat_dt_prop(node, "samsung,mfc-l", &len); + if (!prop || (len != 2 * sizeof(unsigned long))) + return 0; + + mfc_mem->loff = be32_to_cpu(prop[0]); + mfc_mem->lsize = be32_to_cpu(prop[1]); + + prop = of_get_flat_dt_prop(node, "samsung,mfc-r", &len); + if (!prop || (len != 2 * sizeof(unsigned long))) + return 0; + + mfc_mem->roff = be32_to_cpu(prop[0]); + mfc_mem->rsize = be32_to_cpu(prop[1]); + + return 1; +} +#endif From 8d4155dbb184f02c08bd36c5120f2b4dc4f14860 Mon Sep 17 00:00:00 2001 From: Amit Daniel Kachhap Date: Mon, 29 Oct 2012 21:18:01 +0900 Subject: [PATCH 18/32] ARM: EXYNOS: Add devicetree node for TMU driver for exynos4 This patch adds necessary source definations needed for TMU driver and adds devicetree node for exynos4210. Signed-off-by: Amit Daniel Kachhap Signed-off-by: Kukjin Kim --- arch/arm/boot/dts/exynos4210.dtsi | 7 +++++++ arch/arm/mach-exynos/clock-exynos4.c | 4 ++++ arch/arm/mach-exynos/include/mach/irqs.h | 3 +++ arch/arm/mach-exynos/include/mach/map.h | 2 ++ arch/arm/mach-exynos/mach-exynos4-dt.c | 2 ++ 5 files changed, 18 insertions(+) diff --git a/arch/arm/boot/dts/exynos4210.dtsi b/arch/arm/boot/dts/exynos4210.dtsi index 214c557eda7..038de97b35f 100644 --- a/arch/arm/boot/dts/exynos4210.dtsi +++ b/arch/arm/boot/dts/exynos4210.dtsi @@ -303,4 +303,11 @@ #gpio-cells = <4>; }; }; + + tmu@100C0000 { + compatible = "samsung,exynos4210-tmu"; + interrupt-parent = <&combiner>; + reg = <0x100C0000 0x100>; + interrupts = <2 4>; + }; }; diff --git a/arch/arm/mach-exynos/clock-exynos4.c b/arch/arm/mach-exynos/clock-exynos4.c index 6a45c9a9abe..1870bee991b 100644 --- a/arch/arm/mach-exynos/clock-exynos4.c +++ b/arch/arm/mach-exynos/clock-exynos4.c @@ -575,6 +575,10 @@ static struct clk exynos4_init_clocks_off[] = { .name = "adc", .enable = exynos4_clk_ip_peril_ctrl, .ctrlbit = (1 << 15), + }, { + .name = "tmu_apbif", + .enable = exynos4_clk_ip_perir_ctrl, + .ctrlbit = (1 << 17), }, { .name = "keypad", .enable = exynos4_clk_ip_perir_ctrl, diff --git a/arch/arm/mach-exynos/include/mach/irqs.h b/arch/arm/mach-exynos/include/mach/irqs.h index 35bced6f909..5adacd12e43 100644 --- a/arch/arm/mach-exynos/include/mach/irqs.h +++ b/arch/arm/mach-exynos/include/mach/irqs.h @@ -136,6 +136,9 @@ #define EXYNOS4_IRQ_TSI IRQ_SPI(115) #define EXYNOS4_IRQ_SATA IRQ_SPI(116) +#define EXYNOS4_IRQ_TMU_TRIG0 COMBINER_IRQ(2, 4) +#define EXYNOS4_IRQ_TMU_TRIG1 COMBINER_IRQ(3, 4) + #define EXYNOS4_IRQ_SYSMMU_MDMA0_0 COMBINER_IRQ(4, 0) #define EXYNOS4_IRQ_SYSMMU_SSS_0 COMBINER_IRQ(4, 1) #define EXYNOS4_IRQ_SYSMMU_FIMC0_0 COMBINER_IRQ(4, 2) diff --git a/arch/arm/mach-exynos/include/mach/map.h b/arch/arm/mach-exynos/include/mach/map.h index 8480849affb..772acd344cb 100644 --- a/arch/arm/mach-exynos/include/mach/map.h +++ b/arch/arm/mach-exynos/include/mach/map.h @@ -88,6 +88,8 @@ #define EXYNOS4_PA_TWD 0x10500600 #define EXYNOS4_PA_L2CC 0x10502000 +#define EXYNOS4_PA_TMU 0x100C0000 + #define EXYNOS4_PA_MDMA0 0x10810000 #define EXYNOS4_PA_MDMA1 0x12850000 #define EXYNOS4_PA_PDMA0 0x12680000 diff --git a/arch/arm/mach-exynos/mach-exynos4-dt.c b/arch/arm/mach-exynos/mach-exynos4-dt.c index e58d786faf7..0276ae44777 100644 --- a/arch/arm/mach-exynos/mach-exynos4-dt.c +++ b/arch/arm/mach-exynos/mach-exynos4-dt.c @@ -77,6 +77,8 @@ static const struct of_dev_auxdata exynos4_auxdata_lookup[] __initconst = { "exynos4210-spi.2", NULL), OF_DEV_AUXDATA("arm,pl330", EXYNOS4_PA_PDMA0, "dma-pl330.0", NULL), OF_DEV_AUXDATA("arm,pl330", EXYNOS4_PA_PDMA1, "dma-pl330.1", NULL), + OF_DEV_AUXDATA("samsung,exynos4210-tmu", EXYNOS4_PA_TMU, + "exynos-tmu", NULL), {}, }; From ef405e04abd0d4bc3f7082d241517f6db3f5c06d Mon Sep 17 00:00:00 2001 From: Amit Daniel Kachhap Date: Mon, 29 Oct 2012 21:23:29 +0900 Subject: [PATCH 19/32] ARM: EXYNOS: Add devicetree node for TMU driver for exynos5 This patch adds necessary source definations needed for TMU driver and adds devicetree node for exynos5250. Signed-off-by: Amit Daniel Kachhap [kgene.kim@samsung.com: used address value directly in auxdata] Signed-off-by: Kukjin Kim --- arch/arm/boot/dts/exynos5250.dtsi | 6 ++++++ arch/arm/mach-exynos/clock-exynos5.c | 5 +++++ arch/arm/mach-exynos/mach-exynos5-dt.c | 2 ++ 3 files changed, 13 insertions(+) diff --git a/arch/arm/boot/dts/exynos5250.dtsi b/arch/arm/boot/dts/exynos5250.dtsi index 49546bc43ec..670dfdb01a0 100644 --- a/arch/arm/boot/dts/exynos5250.dtsi +++ b/arch/arm/boot/dts/exynos5250.dtsi @@ -74,6 +74,12 @@ interrupts = <0 43 0>, <0 44 0>; }; + tmu@10060000 { + compatible = "samsung,exynos5250-tmu"; + reg = <0x10060000 0x100>; + interrupts = <0 65 0>; + }; + serial@12C00000 { compatible = "samsung,exynos4210-uart"; reg = <0x12C00000 0x100>; diff --git a/arch/arm/mach-exynos/clock-exynos5.c b/arch/arm/mach-exynos/clock-exynos5.c index 8c4e3253cdb..cdfff4b473d 100644 --- a/arch/arm/mach-exynos/clock-exynos5.c +++ b/arch/arm/mach-exynos/clock-exynos5.c @@ -615,6 +615,11 @@ static struct clk exynos5_init_clocks_off[] = { .parent = &exynos5_clk_aclk_66.clk, .enable = exynos5_clk_ip_peric_ctrl, .ctrlbit = (1 << 24), + }, { + .name = "tmu_apbif", + .parent = &exynos5_clk_aclk_66.clk, + .enable = exynos5_clk_ip_peris_ctrl, + .ctrlbit = (1 << 21), }, { .name = "rtc", .parent = &exynos5_clk_aclk_66.clk, diff --git a/arch/arm/mach-exynos/mach-exynos5-dt.c b/arch/arm/mach-exynos/mach-exynos5-dt.c index b7f1154088b..4c0f3369abd 100644 --- a/arch/arm/mach-exynos/mach-exynos5-dt.c +++ b/arch/arm/mach-exynos/mach-exynos5-dt.c @@ -76,6 +76,8 @@ static const struct of_dev_auxdata exynos5250_auxdata_lookup[] __initconst = { OF_DEV_AUXDATA("samsung,exynos5-gsc", EXYNOS5_PA_GSC3, "exynos-gsc.3", NULL), OF_DEV_AUXDATA("samsung,mfc-v6", 0x11000000, "s5p-mfc-v6", NULL), + OF_DEV_AUXDATA("samsung,exynos5250-tmu", 0x10060000, + "exynos-tmu", NULL), {}, }; From 0f7238a1a4727ed515785cc45a55aa88d9933440 Mon Sep 17 00:00:00 2001 From: Tomasz Figa Date: Tue, 6 Nov 2012 15:09:04 +0900 Subject: [PATCH 20/32] ARM: dts: Add support for EXYNOS4X12 SoCs This patch adds device tree sources for EXYNOS4X12 SoC series (currently EXYNOS4212 and EXYNOS4412) and enables mach-exynos4-dt to support these SoCs. Signed-off-by: Tomasz Figa Signed-off-by: Kyungmin Park Signed-off-by: Kukjin Kim --- arch/arm/boot/dts/exynos4212.dtsi | 28 ++++++++++++++++++++++++ arch/arm/boot/dts/exynos4412.dtsi | 28 ++++++++++++++++++++++++ arch/arm/boot/dts/exynos4x12.dtsi | 30 ++++++++++++++++++++++++++ arch/arm/mach-exynos/mach-exynos4-dt.c | 2 ++ 4 files changed, 88 insertions(+) create mode 100644 arch/arm/boot/dts/exynos4212.dtsi create mode 100644 arch/arm/boot/dts/exynos4412.dtsi create mode 100644 arch/arm/boot/dts/exynos4x12.dtsi diff --git a/arch/arm/boot/dts/exynos4212.dtsi b/arch/arm/boot/dts/exynos4212.dtsi new file mode 100644 index 00000000000..c6ae2005961 --- /dev/null +++ b/arch/arm/boot/dts/exynos4212.dtsi @@ -0,0 +1,28 @@ +/* + * Samsung's Exynos4212 SoC device tree source + * + * Copyright (c) 2012 Samsung Electronics Co., Ltd. + * http://www.samsung.com + * + * Samsung's Exynos4212 SoC device nodes are listed in this file. Exynos4212 + * based board files can include this file and provide values for board specfic + * bindings. + * + * Note: This file does not include device nodes for all the controllers in + * Exynos4212 SoC. As device tree coverage for Exynos4212 increases, additional + * nodes can be added to 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. +*/ + +/include/ "exynos4x12.dtsi" + +/ { + compatible = "samsung,exynos4212"; + + gic:interrupt-controller@10490000 { + cpu-offset = <0x8000>; + }; +}; diff --git a/arch/arm/boot/dts/exynos4412.dtsi b/arch/arm/boot/dts/exynos4412.dtsi new file mode 100644 index 00000000000..d7dfe312772 --- /dev/null +++ b/arch/arm/boot/dts/exynos4412.dtsi @@ -0,0 +1,28 @@ +/* + * Samsung's Exynos4412 SoC device tree source + * + * Copyright (c) 2012 Samsung Electronics Co., Ltd. + * http://www.samsung.com + * + * Samsung's Exynos4412 SoC device nodes are listed in this file. Exynos4412 + * based board files can include this file and provide values for board specfic + * bindings. + * + * Note: This file does not include device nodes for all the controllers in + * Exynos4412 SoC. As device tree coverage for Exynos4412 increases, additional + * nodes can be added to 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. +*/ + +/include/ "exynos4x12.dtsi" + +/ { + compatible = "samsung,exynos4412"; + + gic:interrupt-controller@10490000 { + cpu-offset = <0x4000>; + }; +}; diff --git a/arch/arm/boot/dts/exynos4x12.dtsi b/arch/arm/boot/dts/exynos4x12.dtsi new file mode 100644 index 00000000000..906fe8437e7 --- /dev/null +++ b/arch/arm/boot/dts/exynos4x12.dtsi @@ -0,0 +1,30 @@ +/* + * Samsung's Exynos4x12 SoCs device tree source + * + * Copyright (c) 2012 Samsung Electronics Co., Ltd. + * http://www.samsung.com + * + * Samsung's Exynos4x12 SoCs device nodes are listed in this file. Exynos4x12 + * based board files can include this file and provide values for board specfic + * bindings. + * + * Note: This file does not include device nodes for all the controllers in + * Exynos4x12 SoC. As device tree coverage for Exynos4x12 increases, additional + * nodes can be added to 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. +*/ + +/include/ "exynos4.dtsi" + +/ { + combiner:interrupt-controller@10440000 { + interrupts = <0 0 0>, <0 1 0>, <0 2 0>, <0 3 0>, + <0 4 0>, <0 5 0>, <0 6 0>, <0 7 0>, + <0 8 0>, <0 9 0>, <0 10 0>, <0 11 0>, + <0 12 0>, <0 13 0>, <0 14 0>, <0 15 0>, + <0 16 0>, <0 17 0>, <0 18 0>, <0 19 0>; + }; +}; diff --git a/arch/arm/mach-exynos/mach-exynos4-dt.c b/arch/arm/mach-exynos/mach-exynos4-dt.c index eadf4b59e7d..2890bf70a6c 100644 --- a/arch/arm/mach-exynos/mach-exynos4-dt.c +++ b/arch/arm/mach-exynos/mach-exynos4-dt.c @@ -94,6 +94,8 @@ static void __init exynos4_dt_machine_init(void) static char const *exynos4_dt_compat[] __initdata = { "samsung,exynos4210", + "samsung,exynos4212", + "samsung,exynos4412", NULL }; From 86666adc1e594a3e98407da21f5f2bac587ff0cf Mon Sep 17 00:00:00 2001 From: Thomas Abraham Date: Wed, 7 Nov 2012 08:17:43 +0900 Subject: [PATCH 21/32] ARM: dts: add board dts file for EXYNOS4412 based SMDK board Add a minimal board dts file for Samsung EXYNOS4412 based SMDK board. Signed-off-by: Thomas Abraham Signed-off-by: Kukjin Kim --- arch/arm/boot/dts/Makefile | 1 + arch/arm/boot/dts/exynos4412-smdk4412.dts | 45 +++++++++++++++++++++++ 2 files changed, 46 insertions(+) create mode 100644 arch/arm/boot/dts/exynos4412-smdk4412.dts diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile index f37cf9fa5fa..36488a58940 100644 --- a/arch/arm/boot/dts/Makefile +++ b/arch/arm/boot/dts/Makefile @@ -23,6 +23,7 @@ dtb-$(CONFIG_ARCH_DOVE) += dove-cm-a510.dtb \ dtb-$(CONFIG_ARCH_EXYNOS) += exynos4210-origen.dtb \ exynos4210-smdkv310.dtb \ exynos4210-trats.dtb \ + exynos4412-smdk4412.dtb \ exynos5250-smdk5250.dtb dtb-$(CONFIG_ARCH_HIGHBANK) += highbank.dtb dtb-$(CONFIG_ARCH_INTEGRATOR) += integratorap.dtb \ diff --git a/arch/arm/boot/dts/exynos4412-smdk4412.dts b/arch/arm/boot/dts/exynos4412-smdk4412.dts new file mode 100644 index 00000000000..f05bf575cc4 --- /dev/null +++ b/arch/arm/boot/dts/exynos4412-smdk4412.dts @@ -0,0 +1,45 @@ +/* + * Samsung's Exynos4412 based SMDK board device tree source + * + * Copyright (c) 2012-2013 Samsung Electronics Co., Ltd. + * http://www.samsung.com + * + * Device tree source file for Samsung's SMDK4412 board which is based on + * Samsung's Exynos4412 SoC. + * + * 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. +*/ + +/dts-v1/; +/include/ "exynos4412.dtsi" + +/ { + model = "Samsung SMDK evaluation board based on Exynos4412"; + compatible = "samsung,smdk4412", "samsung,exynos4412"; + + memory { + reg = <0x40000000 0x40000000>; + }; + + chosen { + bootargs ="root=/dev/ram0 rw ramdisk=8192 initrd=0x41000000,8M console=ttySAC1,115200 init=/linuxrc"; + }; + + serial@13800000 { + status = "okay"; + }; + + serial@13810000 { + status = "okay"; + }; + + serial@13820000 { + status = "okay"; + }; + + serial@13830000 { + status = "okay"; + }; +}; From ab7b51ff9e3713995fb5f5a2ded22af06aed2847 Mon Sep 17 00:00:00 2001 From: Tomasz Figa Date: Wed, 7 Nov 2012 08:44:51 +0900 Subject: [PATCH 22/32] ARM: EXYNOS: Skip wakeup-int setup if pinctrl driver is used on EXYNOS4X12 This patch modifies the old wakeup interrupt initialization code to detect pinctrl driver by using for_each_matching_node instead of for_each_compatible_node and adds match table for both EXYNOS4210 and EXYNOS4X12. Signed-off-by: Tomasz Figa Signed-off-by: Kyungmin Park Acked-by: Thomas Abraham Signed-off-by: Kukjin Kim --- arch/arm/mach-exynos/common.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/arch/arm/mach-exynos/common.c b/arch/arm/mach-exynos/common.c index 1947be8e5f5..4af8284f359 100644 --- a/arch/arm/mach-exynos/common.c +++ b/arch/arm/mach-exynos/common.c @@ -997,11 +997,14 @@ static int __init exynos_init_irq_eint(void) * platforms switch over to using the pinctrl driver, the wakeup * interrupt support code here can be completely removed. */ + static const struct of_device_id exynos_pinctrl_ids[] = { + { .compatible = "samsung,pinctrl-exynos4210", }, + { .compatible = "samsung,pinctrl-exynos4x12", }, + }; struct device_node *pctrl_np, *wkup_np; - const char *pctrl_compat = "samsung,pinctrl-exynos4210"; const char *wkup_compat = "samsung,exynos4210-wakeup-eint"; - for_each_compatible_node(pctrl_np, NULL, pctrl_compat) { + for_each_matching_node(pctrl_np, exynos_pinctrl_ids) { if (of_device_is_available(pctrl_np)) { wkup_np = of_find_compatible_node(pctrl_np, NULL, wkup_compat); From ba51bdd306a21ab0fabbea3a92541af0ee9fb8f6 Mon Sep 17 00:00:00 2001 From: Tomasz Figa Date: Wed, 7 Nov 2012 08:44:55 +0900 Subject: [PATCH 23/32] gpio: samsung: Skip registration if pinctrl driver is present on EXYNOS4X12 This patch modifies the Samsung GPIO driver to check for pinctrl driver presence earlier and use generic matching instead of a single compatible value. This allows us to fix warning about unrecognized SoC in case of EXYNOS4X12, which is not supported by this driver. Signed-off-by: Tomasz Figa Signed-off-by: Kyungmin Park Acked-by: Thomas Abraham Acked-by: Linus Walleij Signed-off-by: Kukjin Kim --- drivers/gpio/gpio-samsung.c | 43 +++++++++++++++++++------------------ 1 file changed, 22 insertions(+), 21 deletions(-) diff --git a/drivers/gpio/gpio-samsung.c b/drivers/gpio/gpio-samsung.c index a006f0db15a..88f41e51565 100644 --- a/drivers/gpio/gpio-samsung.c +++ b/drivers/gpio/gpio-samsung.c @@ -2797,27 +2797,6 @@ static __init void exynos4_gpiolib_init(void) int group = 0; void __iomem *gpx_base; -#ifdef CONFIG_PINCTRL_SAMSUNG - /* - * This gpio driver includes support for device tree support and - * there are platforms using it. In order to maintain - * compatibility with those platforms, and to allow non-dt - * Exynos4210 platforms to use this gpiolib support, a check - * is added to find out if there is a active pin-controller - * driver support available. If it is available, this gpiolib - * support is ignored and the gpiolib support available in - * pin-controller driver is used. This is a temporary check and - * will go away when all of the Exynos4210 platforms have - * switched to using device tree and the pin-ctrl driver. - */ - struct device_node *pctrl_np; - const char *pctrl_compat = "samsung,pinctrl-exynos4210"; - pctrl_np = of_find_compatible_node(NULL, NULL, pctrl_compat); - if (pctrl_np) - if (of_device_is_available(pctrl_np)) - return; -#endif - /* gpio part1 */ gpio_base1 = ioremap(EXYNOS4_PA_GPIO1, SZ_4K); if (gpio_base1 == NULL) { @@ -3032,6 +3011,28 @@ static __init int samsung_gpiolib_init(void) int i, nr_chips; int group = 0; +#ifdef CONFIG_PINCTRL_SAMSUNG + /* + * This gpio driver includes support for device tree support and there + * are platforms using it. In order to maintain compatibility with those + * platforms, and to allow non-dt Exynos4210 platforms to use this + * gpiolib support, a check is added to find out if there is a active + * pin-controller driver support available. If it is available, this + * gpiolib support is ignored and the gpiolib support available in + * pin-controller driver is used. This is a temporary check and will go + * away when all of the Exynos4210 platforms have switched to using + * device tree and the pin-ctrl driver. + */ + struct device_node *pctrl_np; + static const struct of_device_id exynos_pinctrl_ids[] = { + { .compatible = "samsung,pinctrl-exynos4210", }, + { .compatible = "samsung,pinctrl-exynos4x12", }, + }; + for_each_matching_node(pctrl_np, exynos_pinctrl_ids) + if (pctrl_np && of_device_is_available(pctrl_np)) + return -ENODEV; +#endif + samsung_gpiolib_set_cfg(samsung_gpio_cfgs, ARRAY_SIZE(samsung_gpio_cfgs)); if (soc_is_s3c24xx()) { From 6edc794a5ff245faf60488d32e9fdbeb0aad2223 Mon Sep 17 00:00:00 2001 From: Tomasz Figa Date: Wed, 7 Nov 2012 08:44:59 +0900 Subject: [PATCH 24/32] pinctrl: samsung: Add support for EXYNOS4X12 This patch extends the driver with any necessary SoC-specific definitions to support EXYNOS4X12 SoCs. Signed-off-by: Tomasz Figa Signed-off-by: Kyungmin Park Acked-by: Thomas Abraham Acked-by: Linus Walleij Signed-off-by: Kukjin Kim --- .../bindings/pinctrl/samsung-pinctrl.txt | 1 + drivers/pinctrl/pinctrl-exynos.c | 110 ++++++++++++++++++ drivers/pinctrl/pinctrl-samsung.c | 2 + drivers/pinctrl/pinctrl-samsung.h | 1 + 4 files changed, 114 insertions(+) diff --git a/Documentation/devicetree/bindings/pinctrl/samsung-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/samsung-pinctrl.txt index 63806e2d49c..e97a27856b2 100644 --- a/Documentation/devicetree/bindings/pinctrl/samsung-pinctrl.txt +++ b/Documentation/devicetree/bindings/pinctrl/samsung-pinctrl.txt @@ -8,6 +8,7 @@ on-chip controllers onto these pads. Required Properties: - compatible: should be one of the following. - "samsung,pinctrl-exynos4210": for Exynos4210 compatible pin-controller. + - "samsung,pinctrl-exynos4x12": for Exynos4x12 compatible pin-controller. - "samsung,pinctrl-exynos5250": for Exynos5250 compatible pin-controller. - reg: Base address of the pin controller hardware module and length of diff --git a/drivers/pinctrl/pinctrl-exynos.c b/drivers/pinctrl/pinctrl-exynos.c index 73a0aa27cd5..19fab68a9fb 100644 --- a/drivers/pinctrl/pinctrl-exynos.c +++ b/drivers/pinctrl/pinctrl-exynos.c @@ -566,3 +566,113 @@ struct samsung_pin_ctrl exynos4210_pin_ctrl[] = { .label = "exynos4210-gpio-ctrl2", }, }; + +/* pin banks of exynos4x12 pin-controller 0 */ +static struct samsung_pin_bank exynos4x12_pin_banks0[] = { + EXYNOS_PIN_BANK_EINTG(8, 0x000, "gpa0", 0x00), + EXYNOS_PIN_BANK_EINTG(6, 0x020, "gpa1", 0x04), + EXYNOS_PIN_BANK_EINTG(8, 0x040, "gpb", 0x08), + EXYNOS_PIN_BANK_EINTG(5, 0x060, "gpc0", 0x0c), + EXYNOS_PIN_BANK_EINTG(5, 0x080, "gpc1", 0x10), + EXYNOS_PIN_BANK_EINTG(4, 0x0A0, "gpd0", 0x14), + EXYNOS_PIN_BANK_EINTG(4, 0x0C0, "gpd1", 0x18), + EXYNOS_PIN_BANK_EINTG(8, 0x180, "gpf0", 0x30), + EXYNOS_PIN_BANK_EINTG(8, 0x1A0, "gpf1", 0x34), + EXYNOS_PIN_BANK_EINTG(8, 0x1C0, "gpf2", 0x38), + EXYNOS_PIN_BANK_EINTG(6, 0x1E0, "gpf3", 0x3c), + EXYNOS_PIN_BANK_EINTG(8, 0x240, "gpj0", 0x40), + EXYNOS_PIN_BANK_EINTG(5, 0x260, "gpj1", 0x44), +}; + +/* pin banks of exynos4x12 pin-controller 1 */ +static struct samsung_pin_bank exynos4x12_pin_banks1[] = { + EXYNOS_PIN_BANK_EINTG(7, 0x040, "gpk0", 0x08), + EXYNOS_PIN_BANK_EINTG(7, 0x060, "gpk1", 0x0c), + EXYNOS_PIN_BANK_EINTG(7, 0x080, "gpk2", 0x10), + EXYNOS_PIN_BANK_EINTG(7, 0x0A0, "gpk3", 0x14), + EXYNOS_PIN_BANK_EINTG(7, 0x0C0, "gpl0", 0x18), + EXYNOS_PIN_BANK_EINTG(2, 0x0E0, "gpl1", 0x1c), + EXYNOS_PIN_BANK_EINTG(8, 0x100, "gpl2", 0x20), + EXYNOS_PIN_BANK_EINTG(8, 0x260, "gpm0", 0x24), + EXYNOS_PIN_BANK_EINTG(7, 0x280, "gpm1", 0x28), + EXYNOS_PIN_BANK_EINTG(5, 0x2A0, "gpm2", 0x2c), + EXYNOS_PIN_BANK_EINTG(8, 0x2C0, "gpm3", 0x30), + EXYNOS_PIN_BANK_EINTG(8, 0x2E0, "gpm4", 0x34), + EXYNOS_PIN_BANK_EINTN(6, 0x120, "gpy0"), + EXYNOS_PIN_BANK_EINTN(4, 0x140, "gpy1"), + EXYNOS_PIN_BANK_EINTN(6, 0x160, "gpy2"), + EXYNOS_PIN_BANK_EINTN(8, 0x180, "gpy3"), + EXYNOS_PIN_BANK_EINTN(8, 0x1A0, "gpy4"), + EXYNOS_PIN_BANK_EINTN(8, 0x1C0, "gpy5"), + EXYNOS_PIN_BANK_EINTN(8, 0x1E0, "gpy6"), + EXYNOS_PIN_BANK_EINTW(8, 0xC00, "gpx0", 0x00), + EXYNOS_PIN_BANK_EINTW(8, 0xC20, "gpx1", 0x04), + EXYNOS_PIN_BANK_EINTW(8, 0xC40, "gpx2", 0x08), + EXYNOS_PIN_BANK_EINTW(8, 0xC60, "gpx3", 0x0c), +}; + +/* pin banks of exynos4x12 pin-controller 2 */ +static struct samsung_pin_bank exynos4x12_pin_banks2[] = { + EXYNOS_PIN_BANK_EINTG(7, 0x000, "gpz", 0x00), +}; + +/* pin banks of exynos4x12 pin-controller 3 */ +static struct samsung_pin_bank exynos4x12_pin_banks3[] = { + EXYNOS_PIN_BANK_EINTG(8, 0x000, "gpv0", 0x00), + EXYNOS_PIN_BANK_EINTG(8, 0x020, "gpv1", 0x04), + EXYNOS_PIN_BANK_EINTG(8, 0x040, "gpv2", 0x08), + EXYNOS_PIN_BANK_EINTG(8, 0x060, "gpv3", 0x0c), + EXYNOS_PIN_BANK_EINTG(2, 0x080, "gpv4", 0x10), +}; + +/* + * Samsung pinctrl driver data for Exynos4x12 SoC. Exynos4x12 SoC includes + * four gpio/pin-mux/pinconfig controllers. + */ +struct samsung_pin_ctrl exynos4x12_pin_ctrl[] = { + { + /* pin-controller instance 0 data */ + .pin_banks = exynos4x12_pin_banks0, + .nr_banks = ARRAY_SIZE(exynos4x12_pin_banks0), + .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 = "exynos4x12-gpio-ctrl0", + }, { + /* pin-controller instance 1 data */ + .pin_banks = exynos4x12_pin_banks1, + .nr_banks = ARRAY_SIZE(exynos4x12_pin_banks1), + .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 = "exynos4x12-gpio-ctrl1", + }, { + /* pin-controller instance 2 data */ + .pin_banks = exynos4x12_pin_banks2, + .nr_banks = ARRAY_SIZE(exynos4x12_pin_banks2), + .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 = "exynos4x12-gpio-ctrl2", + }, { + /* pin-controller instance 3 data */ + .pin_banks = exynos4x12_pin_banks3, + .nr_banks = ARRAY_SIZE(exynos4x12_pin_banks3), + .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 = "exynos4x12-gpio-ctrl3", + }, +}; diff --git a/drivers/pinctrl/pinctrl-samsung.c b/drivers/pinctrl/pinctrl-samsung.c index fc34cac8a1b..81c9896d4f6 100644 --- a/drivers/pinctrl/pinctrl-samsung.c +++ b/drivers/pinctrl/pinctrl-samsung.c @@ -947,6 +947,8 @@ static int __devinit samsung_pinctrl_probe(struct platform_device *pdev) static const struct of_device_id samsung_pinctrl_dt_match[] = { { .compatible = "samsung,pinctrl-exynos4210", .data = (void *)exynos4210_pin_ctrl }, + { .compatible = "samsung,pinctrl-exynos4x12", + .data = (void *)exynos4x12_pin_ctrl }, {}, }; MODULE_DEVICE_TABLE(of, samsung_pinctrl_dt_match); diff --git a/drivers/pinctrl/pinctrl-samsung.h b/drivers/pinctrl/pinctrl-samsung.h index 0670d9ea43f..5addfd16e3c 100644 --- a/drivers/pinctrl/pinctrl-samsung.h +++ b/drivers/pinctrl/pinctrl-samsung.h @@ -236,5 +236,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 exynos4x12_pin_ctrl[]; #endif /* __PINCTRL_SAMSUNG_H */ From 64a574344dadbee5d01819d9d73b594d3cbe448e Mon Sep 17 00:00:00 2001 From: Tomasz Figa Date: Wed, 7 Nov 2012 08:50:40 +0900 Subject: [PATCH 25/32] ARM: dts: Add nodes for pin controllers for exynos4x12 This patch adds nodes for pin controllers available on EXYNOS4X12 SoCs supported by pinctrl-samsung driver. Signed-off-by: Tomasz Figa Signed-off-by: Kyungmin Park Acked-by: Thomas Abraham Acked-by: Linus Walleij Signed-off-by: Kukjin Kim --- arch/arm/boot/dts/exynos4x12-pinctrl.dtsi | 965 ++++++++++++++++++++++ arch/arm/boot/dts/exynos4x12.dtsi | 39 + 2 files changed, 1004 insertions(+) create mode 100644 arch/arm/boot/dts/exynos4x12-pinctrl.dtsi diff --git a/arch/arm/boot/dts/exynos4x12-pinctrl.dtsi b/arch/arm/boot/dts/exynos4x12-pinctrl.dtsi new file mode 100644 index 00000000000..56f4669cecc --- /dev/null +++ b/arch/arm/boot/dts/exynos4x12-pinctrl.dtsi @@ -0,0 +1,965 @@ +/* + * Samsung's Exynos4x12 SoCs pin-mux and pin-config device tree source + * + * Copyright (c) 2012 Samsung Electronics Co., Ltd. + * http://www.samsung.com + * + * Samsung's Exynos4x12 SoCs pin-mux and pin-config optiosn are listed as device + * tree nodes are listed 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@11400000 { + gpa0: gpa0 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpa1: gpa1 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpb: gpb { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpc0: gpc0 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpc1: gpc1 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpd0: gpd0 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpd1: gpd1 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpf0: gpf0 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpf1: gpf1 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpf2: gpf2 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpf3: gpf3 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpj0: gpj0 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpj1: gpj1 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + uart0_data: uart0-data { + samsung,pins = "gpa0-0", "gpa0-1"; + samsung,pin-function = <0x2>; + samsung,pin-pud = <0>; + samsung,pin-drv = <0>; + }; + + uart0_fctl: uart0-fctl { + samsung,pins = "gpa0-2", "gpa0-3"; + samsung,pin-function = <2>; + samsung,pin-pud = <0>; + samsung,pin-drv = <0>; + }; + + uart1_data: uart1-data { + samsung,pins = "gpa0-4", "gpa0-5"; + samsung,pin-function = <2>; + samsung,pin-pud = <0>; + samsung,pin-drv = <0>; + }; + + uart1_fctl: uart1-fctl { + samsung,pins = "gpa0-6", "gpa0-7"; + samsung,pin-function = <2>; + samsung,pin-pud = <0>; + samsung,pin-drv = <0>; + }; + + i2c2_bus: i2c2-bus { + samsung,pins = "gpa0-6", "gpa0-7"; + samsung,pin-function = <3>; + samsung,pin-pud = <3>; + samsung,pin-drv = <0>; + }; + + uart2_data: uart2-data { + samsung,pins = "gpa1-0", "gpa1-1"; + samsung,pin-function = <2>; + samsung,pin-pud = <0>; + samsung,pin-drv = <0>; + }; + + uart2_fctl: uart2-fctl { + samsung,pins = "gpa1-2", "gpa1-3"; + samsung,pin-function = <2>; + samsung,pin-pud = <0>; + samsung,pin-drv = <0>; + }; + + uart_audio_a: uart-audio-a { + samsung,pins = "gpa1-0", "gpa1-1"; + samsung,pin-function = <4>; + samsung,pin-pud = <0>; + samsung,pin-drv = <0>; + }; + + i2c3_bus: i2c3-bus { + samsung,pins = "gpa1-2", "gpa1-3"; + samsung,pin-function = <3>; + samsung,pin-pud = <3>; + samsung,pin-drv = <0>; + }; + + uart3_data: uart3-data { + samsung,pins = "gpa1-4", "gpa1-5"; + samsung,pin-function = <2>; + samsung,pin-pud = <0>; + samsung,pin-drv = <0>; + }; + + uart_audio_b: uart-audio-b { + samsung,pins = "gpa1-4", "gpa1-5"; + samsung,pin-function = <4>; + samsung,pin-pud = <0>; + samsung,pin-drv = <0>; + }; + + spi0_bus: spi0-bus { + samsung,pins = "gpb-0", "gpb-2", "gpb-3"; + samsung,pin-function = <2>; + samsung,pin-pud = <3>; + samsung,pin-drv = <0>; + }; + + i2c4_bus: i2c4-bus { + samsung,pins = "gpb-0", "gpb-1"; + samsung,pin-function = <3>; + samsung,pin-pud = <3>; + samsung,pin-drv = <0>; + }; + + spi1_bus: spi1-bus { + samsung,pins = "gpb-4", "gpb-6", "gpb-7"; + samsung,pin-function = <2>; + samsung,pin-pud = <3>; + samsung,pin-drv = <0>; + }; + + i2c5_bus: i2c5-bus { + samsung,pins = "gpb-2", "gpb-3"; + samsung,pin-function = <3>; + samsung,pin-pud = <3>; + samsung,pin-drv = <0>; + }; + + i2s1_bus: i2s1-bus { + samsung,pins = "gpc0-0", "gpc0-1", "gpc0-2", "gpc0-3", + "gpc0-4"; + samsung,pin-function = <2>; + samsung,pin-pud = <0>; + samsung,pin-drv = <0>; + }; + + pcm1_bus: pcm1-bus { + samsung,pins = "gpc0-0", "gpc0-1", "gpc0-2", "gpc0-3", + "gpc0-4"; + samsung,pin-function = <3>; + samsung,pin-pud = <0>; + samsung,pin-drv = <0>; + }; + + ac97_bus: ac97-bus { + samsung,pins = "gpc0-0", "gpc0-1", "gpc0-2", "gpc0-3", + "gpc0-4"; + samsung,pin-function = <4>; + samsung,pin-pud = <0>; + samsung,pin-drv = <0>; + }; + + i2s2_bus: i2s2-bus { + samsung,pins = "gpc1-0", "gpc1-1", "gpc1-2", "gpc1-3", + "gpc1-4"; + samsung,pin-function = <2>; + samsung,pin-pud = <0>; + samsung,pin-drv = <0>; + }; + + pcm2_bus: pcm2-bus { + samsung,pins = "gpc1-0", "gpc1-1", "gpc1-2", "gpc1-3", + "gpc1-4"; + samsung,pin-function = <3>; + samsung,pin-pud = <0>; + samsung,pin-drv = <0>; + }; + + spdif_bus: spdif-bus { + samsung,pins = "gpc1-0", "gpc1-1"; + samsung,pin-function = <4>; + samsung,pin-pud = <0>; + samsung,pin-drv = <0>; + }; + + i2c6_bus: i2c6-bus { + samsung,pins = "gpc1-3", "gpc1-4"; + samsung,pin-function = <4>; + samsung,pin-pud = <3>; + samsung,pin-drv = <0>; + }; + + spi2_bus: spi2-bus { + samsung,pins = "gpc1-1", "gpc1-3", "gpc1-4"; + samsung,pin-function = <5>; + samsung,pin-pud = <3>; + samsung,pin-drv = <0>; + }; + + pwm0_out: pwm0-out { + samsung,pins = "gpd0-0"; + samsung,pin-function = <2>; + samsung,pin-pud = <0>; + samsung,pin-drv = <0>; + }; + + pwm1_out: pwm1-out { + samsung,pins = "gpd0-1"; + samsung,pin-function = <2>; + samsung,pin-pud = <0>; + samsung,pin-drv = <0>; + }; + + lcd_ctrl: lcd-ctrl { + samsung,pins = "gpd0-0", "gpd0-1"; + samsung,pin-function = <3>; + samsung,pin-pud = <0>; + samsung,pin-drv = <0>; + }; + + i2c7_bus: i2c7-bus { + samsung,pins = "gpd0-2", "gpd0-3"; + samsung,pin-function = <3>; + samsung,pin-pud = <3>; + samsung,pin-drv = <0>; + }; + + pwm2_out: pwm2-out { + samsung,pins = "gpd0-2"; + samsung,pin-function = <2>; + samsung,pin-pud = <0>; + samsung,pin-drv = <0>; + }; + + pwm3_out: pwm3-out { + samsung,pins = "gpd0-3"; + samsung,pin-function = <2>; + samsung,pin-pud = <0>; + samsung,pin-drv = <0>; + }; + + i2c0_bus: i2c0-bus { + samsung,pins = "gpd1-0", "gpd1-1"; + samsung,pin-function = <2>; + samsung,pin-pud = <3>; + samsung,pin-drv = <0>; + }; + + mipi0_clk: mipi0-clk { + samsung,pins = "gpd1-0", "gpd1-1"; + samsung,pin-function = <3>; + samsung,pin-pud = <0>; + samsung,pin-drv = <0>; + }; + + i2c1_bus: i2c1-bus { + samsung,pins = "gpd1-2", "gpd1-3"; + samsung,pin-function = <2>; + samsung,pin-pud = <3>; + samsung,pin-drv = <0>; + }; + + mipi1_clk: mipi1-clk { + samsung,pins = "gpd1-2", "gpd1-3"; + samsung,pin-function = <3>; + samsung,pin-pud = <0>; + samsung,pin-drv = <0>; + }; + + lcd_clk: lcd-clk { + samsung,pins = "gpf0-0", "gpf0-1", "gpf0-2", "gpf0-3"; + samsung,pin-function = <2>; + samsung,pin-pud = <0>; + samsung,pin-drv = <0>; + }; + + lcd_data16: lcd-data-width16 { + samsung,pins = "gpf0-7", "gpf1-0", "gpf1-1", "gpf1-2", + "gpf1-3", "gpf1-6", "gpf1-7", "gpf2-0", + "gpf2-1", "gpf2-2", "gpf2-3", "gpf2-7", + "gpf3-0", "gpf3-1", "gpf3-2", "gpf3-3"; + samsung,pin-function = <2>; + samsung,pin-pud = <0>; + samsung,pin-drv = <0>; + }; + + lcd_data18: lcd-data-width18 { + samsung,pins = "gpf0-6", "gpf0-7", "gpf1-0", "gpf1-1", + "gpf1-2", "gpf1-3", "gpf1-6", "gpf1-7", + "gpf2-0", "gpf2-1", "gpf2-2", "gpf2-3", + "gpf2-6", "gpf2-7", "gpf3-0", "gpf3-1", + "gpf3-2", "gpf3-3"; + samsung,pin-function = <2>; + samsung,pin-pud = <0>; + samsung,pin-drv = <0>; + }; + + lcd_data24: lcd-data-width24 { + samsung,pins = "gpf0-4", "gpf0-5", "gpf0-6", "gpf0-7", + "gpf1-0", "gpf1-1", "gpf1-2", "gpf1-3", + "gpf1-4", "gpf1-5", "gpf1-6", "gpf1-7", + "gpf2-0", "gpf2-1", "gpf2-2", "gpf2-3", + "gpf2-4", "gpf2-5", "gpf2-6", "gpf2-7", + "gpf3-0", "gpf3-1", "gpf3-2", "gpf3-3"; + samsung,pin-function = <2>; + samsung,pin-pud = <0>; + samsung,pin-drv = <0>; + }; + + lcd_ldi: lcd-ldi { + samsung,pins = "gpf3-4"; + samsung,pin-function = <2>; + samsung,pin-pud = <0>; + samsung,pin-drv = <0>; + }; + + cam_port_a: cam-port-a { + samsung,pins = "gpj0-0", "gpj0-1", "gpj0-2", "gpj0-3", + "gpj0-4", "gpj0-5", "gpj0-6", "gpj0-7", + "gpj1-0", "gpj1-1", "gpj1-2", "gpj1-3", + "gpj1-4"; + samsung,pin-function = <2>; + samsung,pin-pud = <3>; + samsung,pin-drv = <0>; + }; + }; + + pinctrl@11000000 { + gpk0: gpk0 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpk1: gpk1 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpk2: gpk2 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpk3: gpk3 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpl0: gpl0 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpl1: gpl1 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpl2: gpl2 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpm0: gpm0 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpm1: gpm1 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpm2: gpm2 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpm3: gpm3 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpm4: gpm4 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpy0: gpy0 { + gpio-controller; + #gpio-cells = <2>; + }; + + gpy1: gpy1 { + gpio-controller; + #gpio-cells = <2>; + }; + + gpy2: gpy2 { + gpio-controller; + #gpio-cells = <2>; + }; + + gpy3: gpy3 { + gpio-controller; + #gpio-cells = <2>; + }; + + gpy4: gpy4 { + gpio-controller; + #gpio-cells = <2>; + }; + + gpy5: gpy5 { + gpio-controller; + #gpio-cells = <2>; + }; + + gpy6: gpy6 { + gpio-controller; + #gpio-cells = <2>; + }; + + gpx0: gpx0 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + 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>; + #interrupt-cells = <2>; + }; + + gpx1: gpx1 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + 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>; + #interrupt-cells = <2>; + }; + + gpx2: gpx2 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpx3: gpx3 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + sd0_clk: sd0-clk { + samsung,pins = "gpk0-0"; + samsung,pin-function = <2>; + samsung,pin-pud = <0>; + samsung,pin-drv = <0>; + }; + + sd0_cmd: sd0-cmd { + samsung,pins = "gpk0-1"; + samsung,pin-function = <2>; + samsung,pin-pud = <0>; + samsung,pin-drv = <0>; + }; + + sd0_cd: sd0-cd { + samsung,pins = "gpk0-2"; + samsung,pin-function = <2>; + samsung,pin-pud = <3>; + samsung,pin-drv = <0>; + }; + + sd0_bus1: sd0-bus-width1 { + samsung,pins = "gpk0-3"; + samsung,pin-function = <2>; + samsung,pin-pud = <3>; + samsung,pin-drv = <0>; + }; + + sd0_bus4: sd0-bus-width4 { + samsung,pins = "gpk0-3", "gpk0-4", "gpk0-5", "gpk0-6"; + samsung,pin-function = <2>; + samsung,pin-pud = <3>; + samsung,pin-drv = <0>; + }; + + sd0_bus8: sd0-bus-width8 { + samsung,pins = "gpk1-3", "gpk1-4", "gpk1-5", "gpk1-6"; + samsung,pin-function = <3>; + samsung,pin-pud = <3>; + samsung,pin-drv = <0>; + }; + + sd4_clk: sd4-clk { + samsung,pins = "gpk0-0"; + samsung,pin-function = <3>; + samsung,pin-pud = <0>; + samsung,pin-drv = <0>; + }; + + sd4_cmd: sd4-cmd { + samsung,pins = "gpk0-1"; + samsung,pin-function = <3>; + samsung,pin-pud = <0>; + samsung,pin-drv = <0>; + }; + + sd4_cd: sd4-cd { + samsung,pins = "gpk0-2"; + samsung,pin-function = <3>; + samsung,pin-pud = <3>; + samsung,pin-drv = <0>; + }; + + sd4_bus1: sd4-bus-width1 { + samsung,pins = "gpk0-3"; + samsung,pin-function = <3>; + samsung,pin-pud = <3>; + samsung,pin-drv = <0>; + }; + + sd4_bus4: sd4-bus-width4 { + samsung,pins = "gpk0-3", "gpk0-4", "gpk0-5", "gpk0-6"; + samsung,pin-function = <3>; + samsung,pin-pud = <3>; + samsung,pin-drv = <0>; + }; + + sd4_bus8: sd4-bus-width8 { + samsung,pins = "gpk1-3", "gpk1-4", "gpk1-5", "gpk1-6"; + samsung,pin-function = <3>; + samsung,pin-pud = <4>; + samsung,pin-drv = <0>; + }; + + sd1_clk: sd1-clk { + samsung,pins = "gpk1-0"; + samsung,pin-function = <2>; + samsung,pin-pud = <0>; + samsung,pin-drv = <0>; + }; + + sd1_cmd: sd1-cmd { + samsung,pins = "gpk1-1"; + samsung,pin-function = <2>; + samsung,pin-pud = <0>; + samsung,pin-drv = <0>; + }; + + sd1_cd: sd1-cd { + samsung,pins = "gpk1-2"; + samsung,pin-function = <2>; + samsung,pin-pud = <3>; + samsung,pin-drv = <0>; + }; + + sd1_bus1: sd1-bus-width1 { + samsung,pins = "gpk1-3"; + samsung,pin-function = <2>; + samsung,pin-pud = <3>; + samsung,pin-drv = <0>; + }; + + sd1_bus4: sd1-bus-width4 { + samsung,pins = "gpk1-3", "gpk1-4", "gpk1-5", "gpk1-6"; + samsung,pin-function = <2>; + samsung,pin-pud = <3>; + samsung,pin-drv = <0>; + }; + + sd2_clk: sd2-clk { + samsung,pins = "gpk2-0"; + samsung,pin-function = <2>; + samsung,pin-pud = <0>; + samsung,pin-drv = <0>; + }; + + sd2_cmd: sd2-cmd { + samsung,pins = "gpk2-1"; + samsung,pin-function = <2>; + samsung,pin-pud = <0>; + samsung,pin-drv = <0>; + }; + + sd2_cd: sd2-cd { + samsung,pins = "gpk2-2"; + samsung,pin-function = <2>; + samsung,pin-pud = <3>; + samsung,pin-drv = <0>; + }; + + sd2_bus1: sd2-bus-width1 { + samsung,pins = "gpk2-3"; + samsung,pin-function = <2>; + samsung,pin-pud = <3>; + samsung,pin-drv = <0>; + }; + + sd2_bus4: sd2-bus-width4 { + samsung,pins = "gpk2-3", "gpk2-4", "gpk2-5", "gpk2-6"; + samsung,pin-function = <2>; + samsung,pin-pud = <3>; + samsung,pin-drv = <0>; + }; + + sd2_bus8: sd2-bus-width8 { + samsung,pins = "gpk3-3", "gpk3-4", "gpk3-5", "gpk3-6"; + samsung,pin-function = <3>; + samsung,pin-pud = <3>; + samsung,pin-drv = <0>; + }; + + sd3_clk: sd3-clk { + samsung,pins = "gpk3-0"; + samsung,pin-function = <2>; + samsung,pin-pud = <0>; + samsung,pin-drv = <0>; + }; + + sd3_cmd: sd3-cmd { + samsung,pins = "gpk3-1"; + samsung,pin-function = <2>; + samsung,pin-pud = <0>; + samsung,pin-drv = <0>; + }; + + sd3_cd: sd3-cd { + samsung,pins = "gpk3-2"; + samsung,pin-function = <2>; + samsung,pin-pud = <3>; + samsung,pin-drv = <0>; + }; + + sd3_bus1: sd3-bus-width1 { + samsung,pins = "gpk3-3"; + samsung,pin-function = <2>; + samsung,pin-pud = <3>; + samsung,pin-drv = <0>; + }; + + sd3_bus4: sd3-bus-width4 { + samsung,pins = "gpk3-3", "gpk3-4", "gpk3-5", "gpk3-6"; + samsung,pin-function = <2>; + samsung,pin-pud = <3>; + samsung,pin-drv = <0>; + }; + + keypad_col0: keypad-col0 { + samsung,pins = "gpl2-0"; + samsung,pin-function = <3>; + samsung,pin-pud = <0>; + samsung,pin-drv = <0>; + }; + + keypad_col1: keypad-col1 { + samsung,pins = "gpl2-1"; + samsung,pin-function = <3>; + samsung,pin-pud = <0>; + samsung,pin-drv = <0>; + }; + + keypad_col2: keypad-col2 { + samsung,pins = "gpl2-2"; + samsung,pin-function = <3>; + samsung,pin-pud = <0>; + samsung,pin-drv = <0>; + }; + + keypad_col3: keypad-col3 { + samsung,pins = "gpl2-3"; + samsung,pin-function = <3>; + samsung,pin-pud = <0>; + samsung,pin-drv = <0>; + }; + + keypad_col4: keypad-col4 { + samsung,pins = "gpl2-4"; + samsung,pin-function = <3>; + samsung,pin-pud = <0>; + samsung,pin-drv = <0>; + }; + + keypad_col5: keypad-col5 { + samsung,pins = "gpl2-5"; + samsung,pin-function = <3>; + samsung,pin-pud = <0>; + samsung,pin-drv = <0>; + }; + + keypad_col6: keypad-col6 { + samsung,pins = "gpl2-6"; + samsung,pin-function = <3>; + samsung,pin-pud = <0>; + samsung,pin-drv = <0>; + }; + + keypad_col7: keypad-col7 { + samsung,pins = "gpl2-7"; + samsung,pin-function = <3>; + samsung,pin-pud = <0>; + samsung,pin-drv = <0>; + }; + + cam_port_b: cam-port-b { + samsung,pins = "gpm0-0", "gpm0-1", "gpm0-2", "gpm0-3", + "gpm0-4", "gpm0-5", "gpm0-6", "gpm0-7", + "gpm1-0", "gpm1-1", "gpm2-0", "gpm2-1", + "gpm2-2"; + samsung,pin-function = <3>; + samsung,pin-pud = <3>; + samsung,pin-drv = <0>; + }; + + eint0: ext-int0 { + samsung,pins = "gpx0-0"; + samsung,pin-function = <0xf>; + samsung,pin-pud = <0>; + samsung,pin-drv = <0>; + }; + + eint8: ext-int8 { + samsung,pins = "gpx1-0"; + samsung,pin-function = <0xf>; + samsung,pin-pud = <0>; + samsung,pin-drv = <0>; + }; + + eint15: ext-int15 { + samsung,pins = "gpx1-7"; + samsung,pin-function = <0xf>; + samsung,pin-pud = <0>; + samsung,pin-drv = <0>; + }; + + eint16: ext-int16 { + samsung,pins = "gpx2-0"; + samsung,pin-function = <0xf>; + samsung,pin-pud = <0>; + samsung,pin-drv = <0>; + }; + + eint31: ext-int31 { + samsung,pins = "gpx3-7"; + samsung,pin-function = <0xf>; + samsung,pin-pud = <0>; + samsung,pin-drv = <0>; + }; + }; + + pinctrl@03860000 { + gpz: gpz { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + i2s0_bus: i2s0-bus { + samsung,pins = "gpz-0", "gpz-1", "gpz-2", "gpz-3", + "gpz-4", "gpz-5", "gpz-6"; + samsung,pin-function = <0x2>; + samsung,pin-pud = <0>; + samsung,pin-drv = <0>; + }; + + pcm0_bus: pcm0-bus { + samsung,pins = "gpz-0", "gpz-1", "gpz-2", "gpz-3", + "gpz-4"; + samsung,pin-function = <0x3>; + samsung,pin-pud = <0>; + samsung,pin-drv = <0>; + }; + }; + + pinctrl@106E0000 { + gpv0: gpv0 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpv1: gpv1 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpv2: gpv2 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpv3: gpv3 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpv4: gpv4 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + c2c_bus: c2c-bus { + samsung,pins = "gpv0-0", "gpv0-1", "gpv0-2", "gpv0-3", + "gpv0-4", "gpv0-5", "gpv0-6", "gpv0-7", + "gpv1-0", "gpv1-1", "gpv1-2", "gpv1-3", + "gpv1-4", "gpv1-5", "gpv1-6", "gpv1-7", + "gpv2-0", "gpv2-1", "gpv2-2", "gpv2-3", + "gpv2-4", "gpv2-5", "gpv2-6", "gpv2-7", + "gpv3-0", "gpv3-1", "gpv3-2", "gpv3-3", + "gpv3-4", "gpv3-5", "gpv3-6", "gpv3-7", + "gpv4-0", "gpv4-1"; + samsung,pin-function = <0x2>; + samsung,pin-pud = <0>; + samsung,pin-drv = <0>; + }; + }; +}; diff --git a/arch/arm/boot/dts/exynos4x12.dtsi b/arch/arm/boot/dts/exynos4x12.dtsi index 906fe8437e7..179a62e46c9 100644 --- a/arch/arm/boot/dts/exynos4x12.dtsi +++ b/arch/arm/boot/dts/exynos4x12.dtsi @@ -18,8 +18,16 @@ */ /include/ "exynos4.dtsi" +/include/ "exynos4x12-pinctrl.dtsi" / { + aliases { + pinctrl0 = &pinctrl_0; + pinctrl1 = &pinctrl_1; + pinctrl2 = &pinctrl_2; + pinctrl3 = &pinctrl_3; + }; + combiner:interrupt-controller@10440000 { interrupts = <0 0 0>, <0 1 0>, <0 2 0>, <0 3 0>, <0 4 0>, <0 5 0>, <0 6 0>, <0 7 0>, @@ -27,4 +35,35 @@ <0 12 0>, <0 13 0>, <0 14 0>, <0 15 0>, <0 16 0>, <0 17 0>, <0 18 0>, <0 19 0>; }; + + pinctrl_0: pinctrl@11400000 { + compatible = "samsung,pinctrl-exynos4x12"; + reg = <0x11400000 0x1000>; + interrupts = <0 47 0>; + }; + + pinctrl_1: pinctrl@11000000 { + compatible = "samsung,pinctrl-exynos4x12"; + reg = <0x11000000 0x1000>; + interrupts = <0 46 0>; + + wakup_eint: wakeup-interrupt-controller { + compatible = "samsung,exynos4210-wakeup-eint"; + interrupt-parent = <&gic>; + interrupts = <0 32 0>; + }; + }; + + pinctrl_2: pinctrl@03860000 { + compatible = "samsung,pinctrl-exynos4x12"; + reg = <0x03860000 0x1000>; + interrupt-parent = <&combiner>; + interrupts = <10 0>; + }; + + pinctrl_3: pinctrl@106E0000 { + compatible = "samsung,pinctrl-exynos4x12"; + reg = <0x106E0000 0x1000>; + interrupts = <0 72 0>; + }; }; From e92501263c03144a553327ac95cf9a760a6661bc Mon Sep 17 00:00:00 2001 From: Tomasz Figa Date: Tue, 20 Nov 2012 16:26:17 +0900 Subject: [PATCH 26/32] ARM: dts: Update for pinctrl-samsung driver for exynos4210-trats This patch updates all parts of Trats dts related to pin configuration to use new GPIO and pinctrl bindings, instead of (now unsupported on Exynos4) legacy gpio-samsung bindings. Signed-off-by: Tomasz Figa Signed-off-by: Kyungmin Park Signed-off-by: Kukjin Kim --- arch/arm/boot/dts/exynos4210-trats.dts | 24 ++++++++---------------- 1 file changed, 8 insertions(+), 16 deletions(-) diff --git a/arch/arm/boot/dts/exynos4210-trats.dts b/arch/arm/boot/dts/exynos4210-trats.dts index a21511c1407..661854b03f8 100644 --- a/arch/arm/boot/dts/exynos4210-trats.dts +++ b/arch/arm/boot/dts/exynos4210-trats.dts @@ -35,7 +35,7 @@ regulator-name = "VMEM_VDD_2.8V"; regulator-min-microvolt = <2800000>; regulator-max-microvolt = <2800000>; - gpio = <&gpk0 2 1 0 0>; + gpio = <&gpk0 2 0>; enable-active-high; }; @@ -43,16 +43,8 @@ bus-width = <8>; non-removable; broken-voltage; - gpios = <&gpk0 0 2 0 3>, - <&gpk0 1 2 0 3>, - <&gpk0 3 2 2 3>, - <&gpk0 4 2 2 3>, - <&gpk0 5 2 2 3>, - <&gpk0 6 2 2 3>, - <&gpk1 3 3 3 3>, - <&gpk1 4 3 3 3>, - <&gpk1 5 3 3 3>, - <&gpk1 6 3 3 3>; + pinctrl-0 = <&sd0_clk &sd0_cmd &sd0_bus8>; + pinctrl-names = "default"; vmmc-supply = <&vemmc_reg>; status = "okay"; }; @@ -77,8 +69,8 @@ samsung,i2c-sda-delay = <100>; samsung,i2c-slave-addr = <0x10>; samsung,i2c-max-bus-freq = <100000>; - gpios = <&gpb 6 3 3 0>, - <&gpb 7 3 3 0>; + pinctrl-0 = <&i2c5_bus>; + pinctrl-names = "default"; status = "okay"; max8997_pmic@66 { @@ -93,9 +85,9 @@ max8997,pmic-ignore-gpiodvs-side-effect; max8997,pmic-buck125-default-dvs-idx = <0>; - max8997,pmic-buck125-dvs-gpios = <&gpx0 5 1 0 0>, - <&gpx0 6 1 0 0>, - <&gpl0 0 1 0 0>; + max8997,pmic-buck125-dvs-gpios = <&gpx0 5 0>, + <&gpx0 6 0>, + <&gpl0 0 0>; max8997,pmic-buck1-dvs-voltage = <1350000>, <1300000>, <1250000>, <1200000>, From 9eb61020a08d8269c2bc9454f7baf42e00b01c87 Mon Sep 17 00:00:00 2001 From: Tomasz Figa Date: Tue, 20 Nov 2012 16:26:17 +0900 Subject: [PATCH 27/32] ARM: dts: Add nodes for GPIO keys available on Trats This patch extends dts file of Samsung Trats board to add support for available GPIO keys using gpio-keys driver. Signed-off-by: Tomasz Figa Signed-off-by: Kyungmin Park Signed-off-by: Kukjin Kim --- arch/arm/boot/dts/exynos4210-trats.dts | 33 ++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/arch/arm/boot/dts/exynos4210-trats.dts b/arch/arm/boot/dts/exynos4210-trats.dts index 661854b03f8..dcfa04b336c 100644 --- a/arch/arm/boot/dts/exynos4210-trats.dts +++ b/arch/arm/boot/dts/exynos4210-trats.dts @@ -65,6 +65,39 @@ status = "okay"; }; + gpio-keys { + compatible = "gpio-keys"; + + vol-down-key { + gpios = <&gpx2 1 1>; + linux,code = <114>; + label = "volume down"; + debounce-interval = <10>; + }; + + vol-up-key { + gpios = <&gpx2 0 1>; + linux,code = <115>; + label = "volume up"; + debounce-interval = <10>; + }; + + power-key { + gpios = <&gpx2 7 1>; + linux,code = <116>; + label = "power"; + debounce-interval = <10>; + gpio-key,wakeup; + }; + + ok-key { + gpios = <&gpx3 5 1>; + linux,code = <352>; + label = "ok"; + debounce-interval = <10>; + }; + }; + i2c@138B0000 { samsung,i2c-sda-delay = <100>; samsung,i2c-slave-addr = <0x10>; From b74cbbc7b6ecf29265a3dbdbdf257e86b4a1f380 Mon Sep 17 00:00:00 2001 From: Tomasz Figa Date: Tue, 20 Nov 2012 16:26:17 +0900 Subject: [PATCH 28/32] ARM: dts: Add node for i2c3 bus for exynos4210-trats This patch adds device tree node for i2c3 bus to device tree source of Samsung Trats board. This bus is used by mms114 touchscreen controller, for which support will be added in separate patch. Signed-off-by: Tomasz Figa Signed-off-by: Kyungmin Park Signed-off-by: Kukjin Kim --- arch/arm/boot/dts/exynos4210-trats.dts | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/arch/arm/boot/dts/exynos4210-trats.dts b/arch/arm/boot/dts/exynos4210-trats.dts index dcfa04b336c..1d502bdd530 100644 --- a/arch/arm/boot/dts/exynos4210-trats.dts +++ b/arch/arm/boot/dts/exynos4210-trats.dts @@ -98,6 +98,15 @@ }; }; + i2c@13890000 { + samsung,i2c-sda-delay = <100>; + samsung,i2c-slave-addr = <0x10>; + samsung,i2c-max-bus-freq = <400000>; + pinctrl-0 = <&i2c3_bus>; + pinctrl-names = "default"; + status = "okay"; + }; + i2c@138B0000 { samsung,i2c-sda-delay = <100>; samsung,i2c-slave-addr = <0x10>; From 50528aa1473a2e5d2cb1a82641afa3aa269e3ddc Mon Sep 17 00:00:00 2001 From: Tomasz Figa Date: Tue, 20 Nov 2012 16:26:18 +0900 Subject: [PATCH 29/32] ARM: dts: Add node for touchscreen voltage regulator for exynos4210-trats This patch adds device tree node for a fixed voltage regulator used for touchscreen on Samsung Trats board. Signed-off-by: Tomasz Figa Signed-off-by: Kyungmin Park Signed-off-by: Kukjin Kim --- arch/arm/boot/dts/exynos4210-trats.dts | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/arch/arm/boot/dts/exynos4210-trats.dts b/arch/arm/boot/dts/exynos4210-trats.dts index 1d502bdd530..5dfd231a98e 100644 --- a/arch/arm/boot/dts/exynos4210-trats.dts +++ b/arch/arm/boot/dts/exynos4210-trats.dts @@ -98,6 +98,15 @@ }; }; + tsp_reg: voltage-regulator { + compatible = "regulator-fixed"; + regulator-name = "TSP_FIXED_VOLTAGES"; + regulator-min-microvolt = <2800000>; + regulator-max-microvolt = <2800000>; + gpio = <&gpl0 3 0>; + enable-active-high; + }; + i2c@13890000 { samsung,i2c-sda-delay = <100>; samsung,i2c-slave-addr = <0x10>; From 0d09bf69fc9f99f0d56c420acb1abb018292632c Mon Sep 17 00:00:00 2001 From: Tomasz Figa Date: Tue, 20 Nov 2012 16:26:18 +0900 Subject: [PATCH 30/32] ARM: dts: Add node for touchscreen for exynos4210-trats This patch adds a device tree node for the Melfas MMS114-controlled touchscreen present on Samsung Trats board. Signed-off-by: Tomasz Figa Signed-off-by: Kyungmin Park Signed-off-by: Kukjin Kim --- arch/arm/boot/dts/exynos4210-trats.dts | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/arch/arm/boot/dts/exynos4210-trats.dts b/arch/arm/boot/dts/exynos4210-trats.dts index 5dfd231a98e..dab2e0865cc 100644 --- a/arch/arm/boot/dts/exynos4210-trats.dts +++ b/arch/arm/boot/dts/exynos4210-trats.dts @@ -114,6 +114,17 @@ pinctrl-0 = <&i2c3_bus>; pinctrl-names = "default"; status = "okay"; + + mms114-touchscreen@48 { + compatible = "melfas,mms114"; + reg = <0x48>; + interrupt-parent = <&gpx0>; + interrupts = <4 2>; + x-size = <720>; + y-size = <1280>; + avdd-supply = <&tsp_reg>; + vdd-supply = <&tsp_reg>; + }; }; i2c@138B0000 { From d36bb0f0401b60f5484700da84a4cf760cd82fe3 Mon Sep 17 00:00:00 2001 From: Tomasz Figa Date: Tue, 20 Nov 2012 20:17:20 +0900 Subject: [PATCH 31/32] ARM: dts: Remove broken-voltage property from sdhci node for exynos4210-trats The broken voltage property has been replaced with auto detection based on voltages available on vmmc voltage regulator, so there is no use for it now. This patch removes the now unused property from Trats Device Tree sources. Signed-off-by: Tomasz Figa Signed-off-by: Kyungmin Park Signed-off-by: Kukjin Kim --- arch/arm/boot/dts/exynos4210-trats.dts | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/arm/boot/dts/exynos4210-trats.dts b/arch/arm/boot/dts/exynos4210-trats.dts index dab2e0865cc..c346b64dff5 100644 --- a/arch/arm/boot/dts/exynos4210-trats.dts +++ b/arch/arm/boot/dts/exynos4210-trats.dts @@ -42,7 +42,6 @@ sdhci_emmc: sdhci@12510000 { bus-width = <8>; non-removable; - broken-voltage; pinctrl-0 = <&sd0_clk &sd0_cmd &sd0_bus8>; pinctrl-names = "default"; vmmc-supply = <&vemmc_reg>; From c47d244a646d08e2161b7fa22c5512e7988762ae Mon Sep 17 00:00:00 2001 From: Vasanth Ananthan Date: Tue, 20 Nov 2012 21:02:11 +0900 Subject: [PATCH 32/32] ARM: EXYNOS: DT Support for SATA and SATA PHY This patch adds Device Nodes for SATA and SATA PHY device. Signed-off-by: Vasanth Ananthan [kgene.kim@samsung.com: removed address definitions as per comments] Signed-off-by: Kukjin Kim --- .../bindings/ata/exynos-sata-phy.txt | 14 ++++++++++++++ .../devicetree/bindings/ata/exynos-sata.txt | 17 +++++++++++++++++ arch/arm/boot/dts/exynos5250-smdk5250.dts | 15 +++++++++++++++ arch/arm/boot/dts/exynos5250.dtsi | 18 ++++++++++++++++++ arch/arm/mach-exynos/mach-exynos5-dt.c | 6 ++++++ 5 files changed, 70 insertions(+) create mode 100644 Documentation/devicetree/bindings/ata/exynos-sata-phy.txt create mode 100644 Documentation/devicetree/bindings/ata/exynos-sata.txt diff --git a/Documentation/devicetree/bindings/ata/exynos-sata-phy.txt b/Documentation/devicetree/bindings/ata/exynos-sata-phy.txt new file mode 100644 index 00000000000..37824fac688 --- /dev/null +++ b/Documentation/devicetree/bindings/ata/exynos-sata-phy.txt @@ -0,0 +1,14 @@ +* Samsung SATA PHY Controller + +SATA PHY nodes are defined to describe on-chip SATA Physical layer controllers. +Each SATA PHY controller should have its own node. + +Required properties: +- compatible : compatible list, contains "samsung,exynos5-sata-phy" +- reg : + +Example: + sata@ffe07000 { + compatible = "samsung,exynos5-sata-phy"; + reg = <0xffe07000 0x1000>; + }; diff --git a/Documentation/devicetree/bindings/ata/exynos-sata.txt b/Documentation/devicetree/bindings/ata/exynos-sata.txt new file mode 100644 index 00000000000..0849f1025e3 --- /dev/null +++ b/Documentation/devicetree/bindings/ata/exynos-sata.txt @@ -0,0 +1,17 @@ +* Samsung AHCI SATA Controller + +SATA nodes are defined to describe on-chip Serial ATA controllers. +Each SATA controller should have its own node. + +Required properties: +- compatible : compatible list, contains "samsung,exynos5-sata" +- interrupts : +- reg : +- samsung,sata-freq : + +Example: + sata@ffe08000 { + compatible = "samsung,exynos5-sata"; + reg = <0xffe08000 0x1000>; + interrupts = <115>; + }; diff --git a/arch/arm/boot/dts/exynos5250-smdk5250.dts b/arch/arm/boot/dts/exynos5250-smdk5250.dts index 21d4ccdb0a5..3f8c2ab1d03 100644 --- a/arch/arm/boot/dts/exynos5250-smdk5250.dts +++ b/arch/arm/boot/dts/exynos5250-smdk5250.dts @@ -55,6 +55,21 @@ }; }; + i2c@121D0000 { + samsung,i2c-sda-delay = <100>; + samsung,i2c-max-bus-freq = <40000>; + samsung,i2c-slave-addr = <0x38>; + + sata-phy { + compatible = "samsung,sata-phy"; + reg = <0x38>; + }; + }; + + sata@122F0000 { + samsung,sata-freq = <66>; + }; + i2c@12C80000 { status = "disabled"; }; diff --git a/arch/arm/boot/dts/exynos5250.dtsi b/arch/arm/boot/dts/exynos5250.dtsi index 670dfdb01a0..e913525a481 100644 --- a/arch/arm/boot/dts/exynos5250.dtsi +++ b/arch/arm/boot/dts/exynos5250.dtsi @@ -104,6 +104,17 @@ interrupts = <0 54 0>; }; + sata@122F0000 { + compatible = "samsung,exynos5-sata-ahci"; + reg = <0x122F0000 0x1ff>; + interrupts = <0 115 0>; + }; + + sata-phy@12170000 { + compatible = "samsung,exynos5-sata-phy"; + reg = <0x12170000 0x1ff>; + }; + i2c@12C60000 { compatible = "samsung,s3c2440-i2c"; reg = <0x12C60000 0x100>; @@ -168,6 +179,13 @@ #size-cells = <0>; }; + i2c@121D0000 { + compatible = "samsung,exynos5-sata-phy-i2c"; + reg = <0x121D0000 0x100>; + #address-cells = <1>; + #size-cells = <0>; + }; + spi_0: spi@12d20000 { compatible = "samsung,exynos4210-spi"; reg = <0x12d20000 0x100>; diff --git a/arch/arm/mach-exynos/mach-exynos5-dt.c b/arch/arm/mach-exynos/mach-exynos5-dt.c index 4c0f3369abd..a88c19f5efc 100644 --- a/arch/arm/mach-exynos/mach-exynos5-dt.c +++ b/arch/arm/mach-exynos/mach-exynos5-dt.c @@ -64,6 +64,12 @@ static const struct of_dev_auxdata exynos5250_auxdata_lookup[] __initconst = { "exynos4210-spi.1", NULL), OF_DEV_AUXDATA("samsung,exynos4210-spi", EXYNOS5_PA_SPI2, "exynos4210-spi.2", NULL), + OF_DEV_AUXDATA("samsung,exynos5-sata-ahci", 0x122F0000, + "exynos5-sata", NULL), + OF_DEV_AUXDATA("samsung,exynos5-sata-phy", 0x12170000, + "exynos5-sata-phy", NULL), + OF_DEV_AUXDATA("samsung,exynos5-sata-phy-i2c", 0x121D0000, + "exynos5-sata-phy-i2c", NULL), OF_DEV_AUXDATA("arm,pl330", EXYNOS5_PA_PDMA0, "dma-pl330.0", NULL), OF_DEV_AUXDATA("arm,pl330", EXYNOS5_PA_PDMA1, "dma-pl330.1", NULL), OF_DEV_AUXDATA("arm,pl330", EXYNOS5_PA_MDMA1, "dma-pl330.2", NULL),