From 7b59e84a3208a00079695abb98a7f1bcc717d7fe Mon Sep 17 00:00:00 2001 From: Jaehyoung Choi Date: Tue, 21 May 2019 13:34:05 +0900 Subject: [PATCH] [RAMEN9610-19588][COMMON] pinctrl: samsung: Add Exynos pin debug state In pin drvdata, you can see the current status of each pin. Change-Id: I1eca9c3e5cbff60fba4bda6530a9f8435eaab28b Signed-off-by: Jaehyoung Choi Signed-off-by: Shinbeom Choi Signed-off-by: Kim Gunho --- drivers/pinctrl/samsung/pinctrl-exynos.c | 4 +- drivers/pinctrl/samsung/pinctrl-samsung.c | 63 +++++++++++++++++++++-- drivers/pinctrl/samsung/pinctrl-samsung.h | 5 +- 3 files changed, 67 insertions(+), 5 deletions(-) diff --git a/drivers/pinctrl/samsung/pinctrl-exynos.c b/drivers/pinctrl/samsung/pinctrl-exynos.c index a684ca2c7d63..d82d8478b218 100644 --- a/drivers/pinctrl/samsung/pinctrl-exynos.c +++ b/drivers/pinctrl/samsung/pinctrl-exynos.c @@ -154,7 +154,7 @@ static int exynos_irq_request_resources(struct irq_data *irqd) struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd); const struct samsung_pin_bank_type *bank_type = bank->type; unsigned long reg_con, flags; - unsigned int shift, mask, con; + unsigned int shift, mask, con, pin; int ret; ret = gpiochip_lock_as_irq(&bank->gpio_chip, irqd->hwirq); @@ -176,6 +176,8 @@ static int exynos_irq_request_resources(struct irq_data *irqd) con |= EXYNOS_PIN_FUNC_EINT << shift; writel(con, bank->pctl_base + reg_con); + pin = bank->grange.pin_base + irqd->hwirq - bank->drvdata->pin_base; + bank->drvdata->pin_groups[pin].state[PINCFG_TYPE_FUNC] = EXYNOS_PIN_FUNC_EINT; spin_unlock_irqrestore(&bank->slock, flags); return 0; diff --git a/drivers/pinctrl/samsung/pinctrl-samsung.c b/drivers/pinctrl/samsung/pinctrl-samsung.c index 80c8c54d6930..d6c5a9fe6d13 100644 --- a/drivers/pinctrl/samsung/pinctrl-samsung.c +++ b/drivers/pinctrl/samsung/pinctrl-samsung.c @@ -449,8 +449,12 @@ static void samsung_pinmux_setup(struct pinctrl_dev *pctldev, unsigned selector, data = readl(reg + type->reg_offset[PINCFG_TYPE_FUNC]); data &= ~(mask << shift); data |= func->val << shift; + writel(data, reg + type->reg_offset[PINCFG_TYPE_FUNC]); + drvdata->pin_groups[grp->pins[0] - drvdata->pin_base].state[PINCFG_TYPE_FUNC] = + ((data >> shift) & mask); + spin_unlock_irqrestore(&bank->slock, flags); } @@ -504,8 +508,11 @@ static int samsung_pinconf_rw(struct pinctrl_dev *pctldev, unsigned int pin, if (set) { cfg_value = PINCFG_UNPACK_VALUE(*config); data &= ~(mask << shift); + data |= (cfg_value << shift); writel(data, reg_base + cfg_reg); + drvdata->pin_groups[pin - drvdata->pin_base].state[cfg_type] = + ((data >> shift) & mask); } else { data >>= shift; data &= mask; @@ -637,15 +644,18 @@ static void samsung_gpio_set_value(struct gpio_chip *gc, struct samsung_pin_bank *bank = gpiochip_get_data(gc); const struct samsung_pin_bank_type *type = bank->type; void __iomem *reg; - u32 data; + u32 data, pin; reg = bank->pctl_base + bank->pctl_offset; + pin = bank->grange.pin_base + offset - bank->drvdata->pin_base; data = readl(reg + type->reg_offset[PINCFG_TYPE_DAT]); data &= ~(1 << offset); if (value) data |= 1 << offset; writel(data, reg + type->reg_offset[PINCFG_TYPE_DAT]); + + bank->drvdata->pin_groups[pin].state[PINCFG_TYPE_DAT] = value; } /* gpiolib gpio_set callback function */ @@ -687,13 +697,14 @@ static int samsung_gpio_set_direction(struct gpio_chip *gc, const struct samsung_pin_bank_type *type; struct samsung_pin_bank *bank; void __iomem *reg; - u32 data, mask, shift; + u32 pin, data, mask, shift; bank = gpiochip_get_data(gc); type = bank->type; reg = bank->pctl_base + bank->pctl_offset + type->reg_offset[PINCFG_TYPE_FUNC]; + pin = bank->grange.pin_base + offset - bank->drvdata->pin_base; mask = (1 << type->fld_width[PINCFG_TYPE_FUNC]) - 1; shift = offset * type->fld_width[PINCFG_TYPE_FUNC]; @@ -705,8 +716,12 @@ static int samsung_gpio_set_direction(struct gpio_chip *gc, data = readl(reg); data &= ~(mask << shift); - if (!input) + + if (!input) { data |= EXYNOS_PIN_FUNC_OUTPUT << shift; + bank->drvdata->pin_groups[pin].state[PINCFG_TYPE_FUNC] = EXYNOS_PIN_FUNC_OUTPUT; + } else + bank->drvdata->pin_groups[pin].state[PINCFG_TYPE_FUNC] = EXYNOS_PIN_FUNC_INPUT; writel(data, reg); return 0; @@ -1070,6 +1085,47 @@ static int samsung_gpiolib_register(struct platform_device *pdev, return 0; } +static int samsung_pinctrl_debug_set(struct samsung_pinctrl_drv_data *drvdata) { + struct samsung_pin_bank *bank; + void __iomem *reg_base; + u32 pin_offset; + unsigned long flags; + enum pincfg_type cfg_type; + const struct samsung_pin_bank_type *type; + u32 data, width, mask, shift, cfg_reg; + int i; + + for (i = 0; i < drvdata->pctl_dev->desc->npins; i++) { + + pin_to_reg_bank(drvdata, i, ®_base, + &pin_offset, &bank); + drvdata->pin_groups[i].state_num = 0; + for (cfg_type = 0; cfg_type < PINCFG_TYPE_NUM; cfg_type++) { + + type = bank->type; + if (!type->fld_width[cfg_type]) + continue; + + spin_lock_irqsave(&bank->slock, flags); + width = type->fld_width[cfg_type]; + cfg_reg = type->reg_offset[cfg_type]; + mask = (1 << width) - 1; + shift = pin_offset * width; + + data = readl(reg_base + cfg_reg); + + data >>= shift; + data &= mask; + + drvdata->pin_groups[i].state[cfg_type] = data; + drvdata->pin_groups[i].state_num++; + spin_unlock_irqrestore(&bank->slock, flags); + } + } + + return 0; +} + static const struct samsung_pin_ctrl * samsung_pinctrl_get_soc_data_for_of_alias(struct platform_device *pdev) { @@ -1241,6 +1297,7 @@ static int samsung_pinctrl_probe(struct platform_device *pdev) /* Add to the global list */ list_add_tail(&drvdata->node, &drvdata_list); + samsung_pinctrl_debug_set(drvdata); return 0; err_unregister: diff --git a/drivers/pinctrl/samsung/pinctrl-samsung.h b/drivers/pinctrl/samsung/pinctrl-samsung.h index 2b9b6c659f8b..efe7a56211ec 100644 --- a/drivers/pinctrl/samsung/pinctrl-samsung.h +++ b/drivers/pinctrl/samsung/pinctrl-samsung.h @@ -273,7 +273,7 @@ struct samsung_pinctrl_drv_data { struct pinctrl_desc pctl; struct pinctrl_dev *pctl_dev; - const struct samsung_pin_group *pin_groups; + struct samsung_pin_group *pin_groups; unsigned int nr_groups; const struct samsung_pmx_func *pmx_functions; unsigned int nr_functions; @@ -305,12 +305,15 @@ struct samsung_pinctrl_of_match_data { * @pins: the pins included in this group. * @num_pins: number of pins included in this group. * @func: the function number to be programmed when selected. + * @state: current pin group state. */ struct samsung_pin_group { const char *name; const unsigned int *pins; u8 num_pins; u8 func; + unsigned int state[PINCFG_TYPE_NUM]; + unsigned int state_num; }; /** -- 2.20.1