+// SPDX-License-Identifier: GPL-2.0+
/*
* Atmel PIO pinctrl driver
*
* Copyright (C) 2016 Atmel Corporation
* Wenyou.Yang <wenyou.yang@atmel.com>
- *
- * SPDX-License-Identifier: GPL-2.0+
*/
#include <common.h>
#define OUTPUT BIT(7)
#define OUTPUT_VAL_SHIFT 8
#define OUTPUT_VAL (0x1 << OUTPUT_VAL_SHIFT)
+#define SLEWRATE_SHIFT 9
+#define SLEWRATE_MASK 0x1
+#define SLEWRATE (SLEWRATE_MASK << SLEWRATE_SHIFT)
#define DEBOUNCE BIT(16)
#define DEBOUNCE_VAL_SHIFT 17
#define DEBOUNCE_VAL (0x3fff << DEBOUNCE_VAL_SHIFT)
* DRIVE_STRENGTH_DEFAULT is just a placeholder to avoid changing the drive
* strength when there is no dt config for it.
*/
-#define DRIVE_STRENGTH_DEFAULT (0 << DRIVE_STRENGTH_SHIFT)
-#define DRIVE_STRENGTH_LOW (1 << DRIVE_STRENGTH_SHIFT)
-#define DRIVE_STRENGTH_MED (2 << DRIVE_STRENGTH_SHIFT)
-#define DRIVE_STRENGTH_HI (3 << DRIVE_STRENGTH_SHIFT)
+enum drive_strength_bit {
+ DRIVE_STRENGTH_BIT_DEF,
+ DRIVE_STRENGTH_BIT_LOW,
+ DRIVE_STRENGTH_BIT_MED,
+ DRIVE_STRENGTH_BIT_HI,
+};
+
+#define DRIVE_STRENGTH_BIT_MSK(name) (DRIVE_STRENGTH_BIT_##name << \
+ DRIVE_STRENGTH_SHIFT)
+
+enum slewrate_bit {
+ SLEWRATE_BIT_DIS,
+ SLEWRATE_BIT_ENA,
+};
+
+#define SLEWRATE_BIT_MSK(name) (SLEWRATE_BIT_##name << SLEWRATE_SHIFT)
enum at91_mux {
AT91_MUX_GPIO = 0,
void (*disable_schmitt_trig)(struct at91_port *pio, u32 mask);
void (*set_drivestrength)(struct at91_port *pio, u32 pin,
u32 strength);
+ void (*set_slewrate)(struct at91_port *pio, u32 pin, u32 slewrate);
};
static u32 two_bit_pin_value_shift_amount(u32 pin)
/* strength is inverse on SAM9x5s with our defines
* 0 = hi, 1 = med, 2 = low, 3 = rsvd */
- setting = DRIVE_STRENGTH_HI - setting;
+ setting = DRIVE_STRENGTH_BIT_MSK(HI) - setting;
set_drive_strength(reg, pin, setting);
}
+static void at91_mux_sam9x60_set_drivestrength(struct at91_port *pio, u32 pin,
+ u32 setting)
+{
+ void *reg = &pio->driver12;
+ u32 tmp;
+
+ if (setting <= DRIVE_STRENGTH_BIT_DEF ||
+ setting == DRIVE_STRENGTH_BIT_MED ||
+ setting > DRIVE_STRENGTH_BIT_HI)
+ return;
+
+ tmp = readl(reg);
+
+ /* Strength is 0: low, 1: hi */
+ if (setting == DRIVE_STRENGTH_BIT_LOW)
+ tmp &= ~BIT(pin);
+ else
+ tmp |= BIT(pin);
+
+ writel(tmp, reg);
+}
+
+static void at91_mux_sam9x60_set_slewrate(struct at91_port *pio, u32 pin,
+ u32 setting)
+{
+ void *reg = &pio->reserved12[3];
+ u32 tmp;
+
+ if (setting < SLEWRATE_BIT_DIS || setting > SLEWRATE_BIT_ENA)
+ return;
+
+ tmp = readl(reg);
+
+ if (setting == SLEWRATE_BIT_DIS)
+ tmp &= ~BIT(pin);
+ else
+ tmp |= BIT(pin);
+
+ writel(tmp, reg);
+}
+
static struct at91_pinctrl_mux_ops at91rm9200_ops = {
.mux_A_periph = at91_mux_set_A_periph,
.mux_B_periph = at91_mux_set_B_periph,
.set_drivestrength = at91_mux_sama5d3_set_drivestrength,
};
+static struct at91_pinctrl_mux_ops sam9x60_ops = {
+ .mux_A_periph = at91_mux_pio3_set_A_periph,
+ .mux_B_periph = at91_mux_pio3_set_B_periph,
+ .mux_C_periph = at91_mux_pio3_set_C_periph,
+ .mux_D_periph = at91_mux_pio3_set_D_periph,
+ .set_deglitch = at91_mux_pio3_set_deglitch,
+ .set_debounce = at91_mux_pio3_set_debounce,
+ .set_pulldown = at91_mux_pio3_set_pulldown,
+ .disable_schmitt_trig = at91_mux_pio3_disable_schmitt_trig,
+ .set_drivestrength = at91_mux_sam9x60_set_drivestrength,
+ .set_slewrate = at91_mux_sam9x60_set_slewrate,
+};
+
static void at91_mux_gpio_disable(struct at91_port *pio, u32 mask)
{
writel(mask, &pio->pdr);
if (ops->set_drivestrength)
ops->set_drivestrength(pio, pin,
(config & DRIVE_STRENGTH) >> DRIVE_STRENGTH_SHIFT);
+ if (ops->set_slewrate)
+ ops->set_slewrate(pio, pin,
+ (config & SLEWRATE) >> SLEWRATE_SHIFT);
return 0;
}
{ .compatible = "atmel,sama5d3-pinctrl", .data = (ulong)&sama5d3_ops },
{ .compatible = "atmel,at91sam9x5-pinctrl", .data = (ulong)&at91sam9x5_ops },
{ .compatible = "atmel,at91rm9200-pinctrl", .data = (ulong)&at91rm9200_ops },
+ { .compatible = "microchip,sam9x60-pinctrl", .data = (ulong)&sam9x60_ops },
{}
};