aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pinctrl/pinctrl-st.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/pinctrl/pinctrl-st.c')
-rw-r--r--drivers/pinctrl/pinctrl-st.c85
1 files changed, 72 insertions, 13 deletions
diff --git a/drivers/pinctrl/pinctrl-st.c b/drivers/pinctrl/pinctrl-st.c
index 9e5ec00084bb..65bf73b70e34 100644
--- a/drivers/pinctrl/pinctrl-st.c
+++ b/drivers/pinctrl/pinctrl-st.c
@@ -206,6 +206,8 @@
#define gpio_chip_to_bank(chip) \
container_of(chip, struct st_gpio_bank, gpio_chip)
+#define pc_to_bank(pc) \
+ container_of(pc, struct st_gpio_bank, pc)
enum st_retime_style {
st_retime_style_none,
@@ -398,6 +400,16 @@ static const struct st_pctl_data stih407_flashdata = {
.rt = 100,
};
+static struct st_pio_control *st_get_pio_control(
+ struct pinctrl_dev *pctldev, int pin)
+{
+ struct pinctrl_gpio_range *range =
+ pinctrl_find_gpio_range_from_pin(pctldev, pin);
+ struct st_gpio_bank *bank = gpio_range_to_bank(range);
+
+ return &bank->pc;
+}
+
/* Low level functions.. */
static inline int st_gpio_bank(int gpio)
{
@@ -460,6 +472,20 @@ static void st_pctl_set_function(struct st_pio_control *pc,
regmap_field_write(alt, val);
}
+static unsigned int st_pctl_get_pin_function(struct st_pio_control *pc, int pin)
+{
+ struct regmap_field *alt = pc->alt;
+ unsigned int val;
+ int offset = pin * 4;
+
+ if (!alt)
+ return 0;
+
+ regmap_field_read(alt, &val);
+
+ return (val >> offset) & 0xf;
+}
+
static unsigned long st_pinconf_delay_to_bit(unsigned int delay,
const struct st_pctl_data *data, unsigned long config)
{
@@ -757,6 +783,35 @@ static int st_gpio_direction_output(struct gpio_chip *chip,
return 0;
}
+static int st_gpio_get_direction(struct gpio_chip *chip, unsigned offset)
+{
+ struct st_gpio_bank *bank = gpio_chip_to_bank(chip);
+ struct st_pio_control pc = bank->pc;
+ unsigned long config;
+ unsigned int direction = 0;
+ unsigned int function;
+ unsigned int value;
+ int i = 0;
+
+ /* Alternate function direction is handled by Pinctrl */
+ function = st_pctl_get_pin_function(&pc, offset);
+ if (function) {
+ st_pinconf_get_direction(&pc, offset, &config);
+ return !ST_PINCONF_UNPACK_OE(config);
+ }
+
+ /*
+ * GPIO direction is handled differently
+ * - See st_gpio_direction() above for an explanation
+ */
+ for (i = 0; i <= 2; i++) {
+ value = readl(bank->base + REG_PIO_PC(i));
+ direction |= ((value >> offset) & 0x1) << i;
+ }
+
+ return (direction == ST_GPIO_DIRECTION_IN);
+}
+
static int st_gpio_xlate(struct gpio_chip *gc,
const struct of_phandle_args *gpiospec, u32 *flags)
{
@@ -904,16 +959,6 @@ static int st_pmx_get_groups(struct pinctrl_dev *pctldev,
return 0;
}
-static struct st_pio_control *st_get_pio_control(
- struct pinctrl_dev *pctldev, int pin)
-{
- struct pinctrl_gpio_range *range =
- pinctrl_find_gpio_range_from_pin(pctldev, pin);
- struct st_gpio_bank *bank = gpio_range_to_bank(range);
-
- return &bank->pc;
-}
-
static int st_pmx_set_mux(struct pinctrl_dev *pctldev, unsigned fselector,
unsigned group)
{
@@ -1011,17 +1056,30 @@ static int st_pinconf_get(struct pinctrl_dev *pctldev,
static void st_pinconf_dbg_show(struct pinctrl_dev *pctldev,
struct seq_file *s, unsigned pin_id)
{
+ struct st_pio_control *pc;
unsigned long config;
+ unsigned int function;
+ int offset = st_gpio_pin(pin_id);
+ char f[16];
mutex_unlock(&pctldev->mutex);
+ pc = st_get_pio_control(pctldev, pin_id);
st_pinconf_get(pctldev, pin_id, &config);
mutex_lock(&pctldev->mutex);
- seq_printf(s, "[OE:%ld,PU:%ld,OD:%ld]\n"
+
+ function = st_pctl_get_pin_function(pc, offset);
+ if (function)
+ snprintf(f, 10, "Alt Fn %d", function);
+ else
+ snprintf(f, 5, "GPIO");
+
+ seq_printf(s, "[OE:%d,PU:%ld,OD:%ld]\t%s\n"
"\t\t[retime:%ld,invclk:%ld,clknotdat:%ld,"
"de:%ld,rt-clk:%ld,rt-delay:%ld]",
- ST_PINCONF_UNPACK_OE(config),
+ !st_gpio_get_direction(&pc_to_bank(pc)->gpio_chip, offset),
ST_PINCONF_UNPACK_PU(config),
ST_PINCONF_UNPACK_OD(config),
+ f,
ST_PINCONF_UNPACK_RT(config),
ST_PINCONF_UNPACK_RT_INVERTCLK(config),
ST_PINCONF_UNPACK_RT_CLKNOTDATA(config),
@@ -1438,6 +1496,7 @@ static struct gpio_chip st_gpio_template = {
.set = st_gpio_set,
.direction_input = st_gpio_direction_input,
.direction_output = st_gpio_direction_output,
+ .get_direction = st_gpio_get_direction,
.ngpio = ST_GPIO_PINS_PER_BANK,
.of_gpio_n_cells = 1,
.of_xlate = st_gpio_xlate,
@@ -1531,7 +1590,7 @@ static int st_gpiolib_register_bank(struct st_pinctrl *info,
return 0;
}
-static struct of_device_id st_pctl_of_match[] = {
+static const struct of_device_id st_pctl_of_match[] = {
{ .compatible = "st,stih415-sbc-pinctrl", .data = &stih415_sbc_data },
{ .compatible = "st,stih415-rear-pinctrl", .data = &stih415_rear_data },
{ .compatible = "st,stih415-left-pinctrl", .data = &stih415_left_data },