|
@@ -56,6 +56,9 @@ static int gpio_banks;
|
|
|
#define DRIVE_STRENGTH_SHIFT 5
|
|
|
#define DRIVE_STRENGTH_MASK 0x3
|
|
|
#define DRIVE_STRENGTH (DRIVE_STRENGTH_MASK << DRIVE_STRENGTH_SHIFT)
|
|
|
+#define OUTPUT (1 << 7)
|
|
|
+#define OUTPUT_VAL_SHIFT 8
|
|
|
+#define OUTPUT_VAL (0x1 << OUTPUT_VAL_SHIFT)
|
|
|
#define DEBOUNCE (1 << 16)
|
|
|
#define DEBOUNCE_VAL_SHIFT 17
|
|
|
#define DEBOUNCE_VAL (0x3fff << DEBOUNCE_VAL_SHIFT)
|
|
@@ -375,6 +378,19 @@ static void at91_mux_set_pullup(void __iomem *pio, unsigned mask, bool on)
|
|
|
writel_relaxed(mask, pio + (on ? PIO_PUER : PIO_PUDR));
|
|
|
}
|
|
|
|
|
|
+static bool at91_mux_get_output(void __iomem *pio, unsigned int pin, bool *val)
|
|
|
+{
|
|
|
+ *val = (readl_relaxed(pio + PIO_ODSR) >> pin) & 0x1;
|
|
|
+ return (readl_relaxed(pio + PIO_OSR) >> pin) & 0x1;
|
|
|
+}
|
|
|
+
|
|
|
+static void at91_mux_set_output(void __iomem *pio, unsigned int mask,
|
|
|
+ bool is_on, bool val)
|
|
|
+{
|
|
|
+ writel_relaxed(mask, pio + (val ? PIO_SODR : PIO_CODR));
|
|
|
+ writel_relaxed(mask, pio + (is_on ? PIO_OER : PIO_ODR));
|
|
|
+}
|
|
|
+
|
|
|
static unsigned at91_mux_get_multidrive(void __iomem *pio, unsigned pin)
|
|
|
{
|
|
|
return (readl_relaxed(pio + PIO_MDSR) >> pin) & 0x1;
|
|
@@ -848,6 +864,7 @@ static int at91_pinconf_get(struct pinctrl_dev *pctldev,
|
|
|
void __iomem *pio;
|
|
|
unsigned pin;
|
|
|
int div;
|
|
|
+ bool out;
|
|
|
|
|
|
*config = 0;
|
|
|
dev_dbg(info->dev, "%s:%d, pin_id=%d", __func__, __LINE__, pin_id);
|
|
@@ -875,6 +892,8 @@ static int at91_pinconf_get(struct pinctrl_dev *pctldev,
|
|
|
if (info->ops->get_drivestrength)
|
|
|
*config |= (info->ops->get_drivestrength(pio, pin)
|
|
|
<< DRIVE_STRENGTH_SHIFT);
|
|
|
+ if (at91_mux_get_output(pio, pin, &out))
|
|
|
+ *config |= OUTPUT | (out << OUTPUT_VAL_SHIFT);
|
|
|
|
|
|
return 0;
|
|
|
}
|
|
@@ -907,6 +926,8 @@ static int at91_pinconf_set(struct pinctrl_dev *pctldev,
|
|
|
if (config & PULL_UP && config & PULL_DOWN)
|
|
|
return -EINVAL;
|
|
|
|
|
|
+ at91_mux_set_output(pio, mask, config & OUTPUT,
|
|
|
+ (config & OUTPUT_VAL) >> OUTPUT_VAL_SHIFT);
|
|
|
at91_mux_set_pullup(pio, mask, config & PULL_UP);
|
|
|
at91_mux_set_multidrive(pio, mask, config & MULTI_DRIVE);
|
|
|
if (info->ops->set_deglitch)
|