diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/net/macb.c | 8 | ||||
-rw-r--r-- | drivers/pinctrl/pinctrl-at91.c | 84 | ||||
-rw-r--r-- | drivers/serial/Kconfig | 9 | ||||
-rw-r--r-- | drivers/serial/atmel_usart.c | 12 | ||||
-rw-r--r-- | drivers/watchdog/Kconfig | 4 | ||||
-rw-r--r-- | drivers/watchdog/at91sam9_wdt.c | 32 |
6 files changed, 120 insertions, 29 deletions
diff --git a/drivers/net/macb.c b/drivers/net/macb.c index 182331f61d..72614164e9 100644 --- a/drivers/net/macb.c +++ b/drivers/net/macb.c @@ -550,8 +550,14 @@ static int macb_phy_init(struct macb_device *macb, const char *name) for (i = 0; i < MACB_AUTONEG_TIMEOUT / 100; i++) { status = macb_mdio_read(macb, MII_BMSR); - if (status & BMSR_LSTATUS) + if (status & BMSR_LSTATUS) { + /* + * Delay a bit after the link is established, + * so that the next xfer does not fail + */ + mdelay(10); break; + } udelay(100); } } diff --git a/drivers/pinctrl/pinctrl-at91.c b/drivers/pinctrl/pinctrl-at91.c index 4bdad62dc9..27f274ff02 100644 --- a/drivers/pinctrl/pinctrl-at91.c +++ b/drivers/pinctrl/pinctrl-at91.c @@ -37,6 +37,9 @@ struct at91_pinctrl_priv { #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) @@ -50,10 +53,22 @@ struct at91_pinctrl_priv { * 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, @@ -90,6 +105,7 @@ struct at91_pinctrl_mux_ops { 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) @@ -238,11 +254,52 @@ static void at91_mux_sam9x5_set_drivestrength(struct at91_port *pio, /* 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, @@ -273,6 +330,19 @@ static struct at91_pinctrl_mux_ops sama5d3_ops = { .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); @@ -339,6 +409,9 @@ static int at91_pinconf_set(struct at91_pinctrl_mux_ops *ops, 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; } @@ -440,6 +513,7 @@ static const struct udevice_id at91_pinctrl_match[] = { { .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 }, {} }; diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index 887cd687c0..fcbb0a81ed 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig @@ -508,6 +508,15 @@ config ATMEL_USART configured in the device tree, and input clock frequency can be got from the clk node. +config SPL_UART_CLOCK + int "SPL fixed UART input clock" + depends on ATMEL_USART && SPL && !SPL_CLK + default 132096000 if ARCH_AT91 + help + Provide a fixed clock value as input to the UART controller. This + might be needed on platforms which can't enable CONFIG_SPL_CLK + because of SPL image size restrictions. + config BCM283X_MU_SERIAL bool "Support for BCM283x Mini-UART" depends on DM_SERIAL && ARCH_BCM283X diff --git a/drivers/serial/atmel_usart.c b/drivers/serial/atmel_usart.c index aa8cdff840..c450a4e08a 100644 --- a/drivers/serial/atmel_usart.c +++ b/drivers/serial/atmel_usart.c @@ -218,6 +218,17 @@ static const struct dm_serial_ops atmel_serial_ops = { .setbrg = atmel_serial_setbrg, }; +#if defined(CONFIG_SPL_BUILD) && !defined(CONFIG_SPL_CLK) +static int atmel_serial_enable_clk(struct udevice *dev) +{ + struct atmel_serial_priv *priv = dev_get_priv(dev); + + /* Use fixed clock value in SPL */ + priv->usart_clk_rate = CONFIG_SPL_UART_CLOCK; + + return 0; +} +#else static int atmel_serial_enable_clk(struct udevice *dev) { struct atmel_serial_priv *priv = dev_get_priv(dev); @@ -245,6 +256,7 @@ static int atmel_serial_enable_clk(struct udevice *dev) return 0; } +#endif static int atmel_serial_probe(struct udevice *dev) { diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index 115fc4551f..34e78beb2a 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -139,10 +139,6 @@ config WDT_AT91 Select this to enable Microchip watchdog timer, which can be found on some AT91 devices. -config AT91_HW_WDT_TIMEOUT - bool "AT91 watchdog timeout specified" - depends on WDT_AT91 - config WDT_MT7621 bool "MediaTek MT7621 watchdog timer support" depends on WDT && ARCH_MT7620 diff --git a/drivers/watchdog/at91sam9_wdt.c b/drivers/watchdog/at91sam9_wdt.c index 13f8772e41..000769d46d 100644 --- a/drivers/watchdog/at91sam9_wdt.c +++ b/drivers/watchdog/at91sam9_wdt.c @@ -17,6 +17,7 @@ #include <asm/io.h> #include <asm/arch/at91_wdt.h> #include <common.h> +#include <div64.h> #include <dm.h> #include <errno.h> #include <wdt.h> @@ -30,28 +31,21 @@ DECLARE_GLOBAL_DATA_PTR; */ #define WDT_SEC2TICKS(s) (((s) << 8) - 1) -/* Hardware timeout in seconds */ -#define WDT_MAX_TIMEOUT 16 -#define WDT_MIN_TIMEOUT 0 -#define WDT_DEFAULT_TIMEOUT 2 - -struct at91_wdt_priv { - void __iomem *regs; - u32 regval; - u32 timeout; -}; - /* * Set the watchdog time interval in 1/256Hz (write-once) * Counter is 12 bit. */ -static int at91_wdt_start(struct udevice *dev, u64 timeout_s, ulong flags) +static int at91_wdt_start(struct udevice *dev, u64 timeout_ms, ulong flags) { struct at91_wdt_priv *priv = dev_get_priv(dev); - u32 timeout = WDT_SEC2TICKS(timeout_s); + u64 timeout; + u32 ticks; - if (timeout_s > WDT_MAX_TIMEOUT || timeout_s < WDT_MIN_TIMEOUT) - timeout = priv->timeout; + /* Calculate timeout in seconds and the resulting ticks */ + timeout = timeout_ms; + do_div(timeout, 1000); + timeout = min_t(u64, timeout, WDT_MAX_TIMEOUT); + ticks = WDT_SEC2TICKS(timeout); /* Check if disabled */ if (readl(priv->regs + AT91_WDT_MR) & AT91_WDT_MR_WDDIS) { @@ -65,12 +59,10 @@ static int at91_wdt_start(struct udevice *dev, u64 timeout_s, ulong flags) * Since WDV is a 12-bit counter, the maximum period is * 4096 / 256 = 16 seconds. */ - priv->regval = AT91_WDT_MR_WDRSTEN /* causes watchdog reset */ | AT91_WDT_MR_WDDBGHLT /* disabled in debug mode */ | AT91_WDT_MR_WDD(0xfff) /* restart at any time */ - | AT91_WDT_MR_WDV(timeout); /* timer value */ - + | AT91_WDT_MR_WDV(ticks); /* timer value */ writel(priv->regval, priv->regs + AT91_WDT_MR); return 0; @@ -115,10 +107,12 @@ static int at91_wdt_probe(struct udevice *dev) if (!priv->regs) return -EINVAL; -#ifdef CONFIG_AT91_HW_WDT_TIMEOUT +#if CONFIG_IS_ENABLED(OF_CONTROL) priv->timeout = dev_read_u32_default(dev, "timeout-sec", WDT_DEFAULT_TIMEOUT); debug("%s: timeout %d", __func__, priv->timeout); +#else + priv->timeout = WDT_DEFAULT_TIMEOUT; #endif debug("%s: Probing wdt%u\n", __func__, dev->seq); |