The previous patch introduced constants to combine pinconfig settings
into one value for easier devicetree handling.
Therefore also add a function, that can separate these bitmaps into
regular generic pinconfig options for handling inside pinctrl drivers.
Signed-off-by: Heiko Stuebner <heiko@...>
.../bindings/pinctrl/pinctrl-bindings.txt | 3 +
drivers/pinctrl/pinconf-generic.c | 61 ++++++++++++++++++++
drivers/pinctrl/pinconf.h | 6 ++
3 files changed, 70 insertions(+), 0 deletions(-)
@@ -132,3 +132,6 @@ controller device.
dt-bindings/pinctrl/pinconfig.h defines a set of constants to combine basic
generic pinconfig settings, like pulls, into one value, that can be used
in pinctrl bindings like <bank pin mux CONFIG>.
+
+This value can then be split into individual generic pinconfig values in the
+driver using pinconf_generic_parse_dt_bitmap.
@@ -139,3 +139,64 @@ void pinconf_generic_dump_config(struct pinctrl_dev *pctldev,
}
EXPORT_SYMBOL_GPL(pinconf_generic_dump_config);
#endif
+
+/*
+ * Maps the devicetree config bits to actual pinconf values.
+ * The array indizes match the bits set in dt-bindings/pinctrl/pinconf.h
+ * and the array should contain an entry for each bit defined there
+ */
+static unsigned long conf_map[] = {
+ PIN_CONF_PACKED(PIN_CONFIG_BIAS_DISABLE, 0),
+ PIN_CONF_PACKED(PIN_CONFIG_BIAS_HIGH_IMPEDANCE, 0),
+ PIN_CONF_PACKED(PIN_CONFIG_BIAS_BUS_HOLD, 0),
+ PIN_CONF_PACKED(PIN_CONFIG_BIAS_PULL_PIN_DEFAULT, 0),
+ PIN_CONF_PACKED(PIN_CONFIG_BIAS_PULL_UP, 0),
+ PIN_CONF_PACKED(PIN_CONFIG_BIAS_PULL_DOWN, 0),
+ PIN_CONF_PACKED(PIN_CONFIG_DRIVE_PUSH_PULL, 0),
+ PIN_CONF_PACKED(PIN_CONFIG_DRIVE_OPEN_DRAIN, 0),
+ PIN_CONF_PACKED(PIN_CONFIG_DRIVE_OPEN_SOURCE, 0),
+ PIN_CONF_PACKED(PIN_CONFIG_INPUT_SCHMITT_ENABLE, 1),
+ PIN_CONF_PACKED(PIN_CONFIG_INPUT_SCHMITT_ENABLE, 0),
+ PIN_CONF_PACKED(PIN_CONFIG_LOW_POWER_MODE, 0),
+ PIN_CONF_PACKED(PIN_CONFIG_OUTPUT, 0),
+ PIN_CONF_PACKED(PIN_CONFIG_OUTPUT, 1),
+};
+
+/*
+ * Parse a pinconf bitmap from a devicetree entry into individual pin configs.
+ * @pinconf: the bitmap containing config bits
+ * @configs: after the function returns contains a pointer to an array of
+ * pin configs
+ * @nconfigs: number of entries of configs
+ */
+int pinconf_generic_parse_dt_bitmap(unsigned long pinconf,
+ unsigned long **configs,
+ unsigned int *nconfigs)
+{
+ int bit;
+ int i;
+ unsigned long *cnf;
+ unsigned int ncnf;
+
+ ncnf = hweight_long(pinconf);
+ cnf = kzalloc(ncnf * sizeof(unsigned long), GFP_KERNEL);
+
+ i = 0;
+ while (pinconf && i < ncnf) {
+ bit = __ffs(pinconf);
+ pinconf &= ~BIT(i);
+
+ if (bit > ARRAY_SIZE(conf_map)) {
+ pr_err("%s: unknown bit %d\n", __func__, bit);
+ kfree(cnf);
+ return -EINVAL;
+ }
+
+ cnf[i] = conf_map[bit];
+ i++;
+ }
+
+ *configs = cnf;
+ *nconfigs = ncnf;
+ return 0;
+}
@@ -123,3 +123,9 @@ static inline void pinconf_generic_dump_config(struct pinctrl_dev *pctldev,
return;
}
#endif
+
+#ifdef CONFIG_GENERIC_PINCONF
+int pinconf_generic_parse_dt_bitmap(unsigned long pinconf,
+ unsigned long **configs,
+ unsigned int *nconfigs);
+#endif