Currently the i2c subsystem rely on the controller device tree to initialize the pinctrl recovery information, part of the drivers does not set this field (rinfo->pinctrl), for example i2c designware driver. The pins information is saved part of the device structure before probe and it's done on pinctrl_bind_pins(). Make the i2c init recovery to get the device pins if it's not initialized by the driver from the device pins. Added new API to get the device pinctrl. Signed-off-by: Hanna Hawa <hhhawa@xxxxxxxxxx> Change Log v2->v3: - Add API to get the device pinctrl - Make the i2c init recovery to get the device pins Change Log v1->v2: - set the rinfo->pinctrl to dev->pins->p instead calling devm_pinctrl_get() --- drivers/i2c/i2c-core-base.c | 7 ++++++- include/linux/pinctrl/devinfo.h | 11 +++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/drivers/i2c/i2c-core-base.c b/drivers/i2c/i2c-core-base.c index 7539b0740351..17eecdcf1cb2 100644 --- a/drivers/i2c/i2c-core-base.c +++ b/drivers/i2c/i2c-core-base.c @@ -34,6 +34,7 @@ #include <linux/of.h> #include <linux/of_irq.h> #include <linux/pinctrl/consumer.h> +#include <linux/pinctrl/devinfo.h> #include <linux/pm_domain.h> #include <linux/pm_runtime.h> #include <linux/pm_wakeirq.h> @@ -282,7 +283,11 @@ static void i2c_gpio_init_pinctrl_recovery(struct i2c_adapter *adap) { struct i2c_bus_recovery_info *bri = adap->bus_recovery_info; struct device *dev = &adap->dev; - struct pinctrl *p = bri->pinctrl; + struct pinctrl *p; + + if (!bri->pinctrl) + bri->pinctrl = dev_pinctrl(dev->parent); + p = bri->pinctrl; /* * we can't change states without pinctrl, so remove the states if diff --git a/include/linux/pinctrl/devinfo.h b/include/linux/pinctrl/devinfo.h index a48ff69acddd..5c00ee115528 100644 --- a/include/linux/pinctrl/devinfo.h +++ b/include/linux/pinctrl/devinfo.h @@ -17,6 +17,7 @@ #ifdef CONFIG_PINCTRL /* The device core acts as a consumer toward pinctrl */ +#include <linux/device.h> #include <linux/pinctrl/consumer.h> /** @@ -40,6 +41,11 @@ struct dev_pin_info { extern int pinctrl_bind_pins(struct device *dev); extern int pinctrl_init_done(struct device *dev); +static inline struct pinctrl *dev_pinctrl(struct device *dev) +{ + return dev->pins && dev->pins->p ? dev->pins->p : NULL; +} + #else struct device; @@ -56,5 +62,10 @@ static inline int pinctrl_init_done(struct device *dev) return 0; } +static inline struct pinctrl *get_device_pinctrl(struct device *dev) +{ + return NULL; +} + #endif /* CONFIG_PINCTRL */ #endif /* PINCTRL_DEVINFO_H */ -- 2.38.1