Message ID | 1484657084-26227-11-git-send-email-m.szyprowski@samsung.com (mailing list archive) |
---|---|
State | Not Applicable |
Headers | show |
Hi Marek, 2017-01-17 21:44 GMT+09:00 Marek Szyprowski <m.szyprowski@samsung.com>: > Pad retention control after suspend/resume cycle should be done from pin > controller driver instead of PMU (power management unit) driver to avoid > possible ordering and logical dependencies. Till now it worked fine only > because PMU driver registered its sys_ops after pin controller. > > This patch adds infrastructure to handle pad retention during pin control > driver resume. > > Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com> > Reviewed-by: Krzysztof Kozlowski <krzk@kernel.org> > --- > drivers/pinctrl/samsung/pinctrl-samsung.c | 12 +++++++++ > drivers/pinctrl/samsung/pinctrl-samsung.h | 42 +++++++++++++++++++++++++++++++ > 2 files changed, 54 insertions(+) > > diff --git a/drivers/pinctrl/samsung/pinctrl-samsung.c b/drivers/pinctrl/samsung/pinctrl-samsung.c > index 59f99ea7e65b..021abd7221f8 100644 > --- a/drivers/pinctrl/samsung/pinctrl-samsung.c > +++ b/drivers/pinctrl/samsung/pinctrl-samsung.c > @@ -1060,6 +1060,13 @@ static int samsung_pinctrl_probe(struct platform_device *pdev) > if (res) > drvdata->irq = res->start; > > + if (ctrl->retention_data) { > + drvdata->retention_ctrl = ctrl->retention_data->init(drvdata, > + ctrl->retention_data); > + if (IS_ERR(drvdata->retention_ctrl)) > + return PTR_ERR(drvdata->retention_ctrl); > + } > + > ret = samsung_gpiolib_register(pdev, drvdata); > if (ret) > return ret; > @@ -1126,6 +1133,8 @@ static void samsung_pinctrl_suspend_dev( > > if (drvdata->suspend) > drvdata->suspend(drvdata); > + if (drvdata->retention_ctrl && drvdata->retention_ctrl->enable) > + drvdata->retention_ctrl->enable(drvdata); Do we need to check presence of ->enable? I think it doesn't make much sense to provide retention_ctrl with NULL enable or disable. > } > > /** > @@ -1173,6 +1182,9 @@ static void samsung_pinctrl_resume_dev(struct samsung_pinctrl_drv_data *drvdata) > if (widths[type]) > writel(bank->pm_save[type], reg + offs[type]); > } > + > + if (drvdata->retention_ctrl && drvdata->retention_ctrl->disable) > + drvdata->retention_ctrl->disable(drvdata); Ditto. > } > > /** > diff --git a/drivers/pinctrl/samsung/pinctrl-samsung.h b/drivers/pinctrl/samsung/pinctrl-samsung.h > index 6f7ce7539a00..5ebbf4137a06 100644 > --- a/drivers/pinctrl/samsung/pinctrl-samsung.h > +++ b/drivers/pinctrl/samsung/pinctrl-samsung.h > @@ -185,10 +185,48 @@ struct samsung_pin_bank { > }; > > /** > + * struct samsung_retention_data: runtime pin-bank retention control data. > + * @regs: array of PMU registers to control pad retention. > + * @nr_regs: number of registers in @regs array. > + * @value: value to store to registers to turn off retention. > + * @refcnt: atomic counter if retention control affects more than one bank. > + * @priv: retention control code private data > + * @on: platform specific callback to enter retention mode. > + * @off: platform specific callback to exit retention mode. s/on/enable/ and s/off/disable/ in comments too. Thanks for taking my bikeshedding into account, though. :) > + **/ > +struct samsung_retention_ctrl { > + const u32 *regs; > + int nr_regs; > + u32 value; > + atomic_t *refcnt; > + void *priv; > + void (*enable)(struct samsung_pinctrl_drv_data *); > + void (*disable)(struct samsung_pinctrl_drv_data *); ^^ Best regards, Tomasz -- To unsubscribe from this list: send the line "unsubscribe linux-samsung-soc" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
diff --git a/drivers/pinctrl/samsung/pinctrl-samsung.c b/drivers/pinctrl/samsung/pinctrl-samsung.c index 59f99ea7e65b..021abd7221f8 100644 --- a/drivers/pinctrl/samsung/pinctrl-samsung.c +++ b/drivers/pinctrl/samsung/pinctrl-samsung.c @@ -1060,6 +1060,13 @@ static int samsung_pinctrl_probe(struct platform_device *pdev) if (res) drvdata->irq = res->start; + if (ctrl->retention_data) { + drvdata->retention_ctrl = ctrl->retention_data->init(drvdata, + ctrl->retention_data); + if (IS_ERR(drvdata->retention_ctrl)) + return PTR_ERR(drvdata->retention_ctrl); + } + ret = samsung_gpiolib_register(pdev, drvdata); if (ret) return ret; @@ -1126,6 +1133,8 @@ static void samsung_pinctrl_suspend_dev( if (drvdata->suspend) drvdata->suspend(drvdata); + if (drvdata->retention_ctrl && drvdata->retention_ctrl->enable) + drvdata->retention_ctrl->enable(drvdata); } /** @@ -1173,6 +1182,9 @@ static void samsung_pinctrl_resume_dev(struct samsung_pinctrl_drv_data *drvdata) if (widths[type]) writel(bank->pm_save[type], reg + offs[type]); } + + if (drvdata->retention_ctrl && drvdata->retention_ctrl->disable) + drvdata->retention_ctrl->disable(drvdata); } /** diff --git a/drivers/pinctrl/samsung/pinctrl-samsung.h b/drivers/pinctrl/samsung/pinctrl-samsung.h index 6f7ce7539a00..5ebbf4137a06 100644 --- a/drivers/pinctrl/samsung/pinctrl-samsung.h +++ b/drivers/pinctrl/samsung/pinctrl-samsung.h @@ -185,10 +185,48 @@ struct samsung_pin_bank { }; /** + * struct samsung_retention_data: runtime pin-bank retention control data. + * @regs: array of PMU registers to control pad retention. + * @nr_regs: number of registers in @regs array. + * @value: value to store to registers to turn off retention. + * @refcnt: atomic counter if retention control affects more than one bank. + * @priv: retention control code private data + * @on: platform specific callback to enter retention mode. + * @off: platform specific callback to exit retention mode. + **/ +struct samsung_retention_ctrl { + const u32 *regs; + int nr_regs; + u32 value; + atomic_t *refcnt; + void *priv; + void (*enable)(struct samsung_pinctrl_drv_data *); + void (*disable)(struct samsung_pinctrl_drv_data *); +}; + +/** + * struct samsung_retention_data: represent a pin-bank retention control data. + * @regs: array of PMU registers to control pad retention. + * @nr_regs: number of registers in @regs array. + * @value: value to store to registers to turn off retention. + * @refcnt: atomic counter if retention control affects more than one bank. + * @init: platform specific callback to initialize retention control. + **/ +struct samsung_retention_data { + const u32 *regs; + int nr_regs; + u32 value; + atomic_t *refcnt; + struct samsung_retention_ctrl *(*init)(struct samsung_pinctrl_drv_data *, + const struct samsung_retention_data *); +}; + +/** * struct samsung_pin_ctrl: represent a pin controller. * @pin_banks: list of pin banks included in this controller. * @nr_banks: number of pin banks. * @nr_ext_resources: number of the extra base address for pin banks. + * @retention_data: configuration data for retention control. * @eint_gpio_init: platform specific callback to setup the external gpio * interrupts for the controller. * @eint_wkup_init: platform specific callback to setup the external wakeup @@ -198,6 +236,7 @@ struct samsung_pin_ctrl { const struct samsung_pin_bank_data *pin_banks; u32 nr_banks; int nr_ext_resources; + const struct samsung_retention_data *retention_data; int (*eint_gpio_init)(struct samsung_pinctrl_drv_data *); int (*eint_wkup_init)(struct samsung_pinctrl_drv_data *); @@ -219,6 +258,7 @@ struct samsung_pin_ctrl { * @nr_function: number of such pin functions. * @pin_base: starting system wide pin number. * @nr_pins: number of pins supported by the controller. + * @retention_ctrl: retention control runtime data. */ struct samsung_pinctrl_drv_data { struct list_head node; @@ -238,6 +278,8 @@ struct samsung_pinctrl_drv_data { unsigned int pin_base; unsigned int nr_pins; + const struct samsung_retention_ctrl *retention_ctrl; + void (*suspend)(struct samsung_pinctrl_drv_data *); void (*resume)(struct samsung_pinctrl_drv_data *); };