From a79d0643f4cac19711cb8d1c2088fc907d47500f Mon Sep 17 00:00:00 2001 From: Wills Wang Date: Wed, 16 Mar 2016 16:59:55 +0800 Subject: drivers: pinctrl: Add simple pinctrl driver for Qualcomm/Atheros ar933x. This is a simple pinctrl driver, it just support uart and spi pin-mux now. Signed-off-by: Wills Wang Reviewed-by: Simon Glass [fixed typo in commit subject line] Signed-off-by: Daniel Schwierzeck --- drivers/pinctrl/Kconfig | 9 +++ drivers/pinctrl/Makefile | 1 + drivers/pinctrl/ath79/Makefile | 5 ++ drivers/pinctrl/ath79/pinctrl_ar933x.c | 136 +++++++++++++++++++++++++++++++++ 4 files changed, 151 insertions(+) create mode 100644 drivers/pinctrl/ath79/Makefile create mode 100644 drivers/pinctrl/ath79/pinctrl_ar933x.c (limited to 'drivers') diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig index 2a69babec4..854d5a500a 100644 --- a/drivers/pinctrl/Kconfig +++ b/drivers/pinctrl/Kconfig @@ -105,6 +105,15 @@ config SPL_PINCONF if PINCTRL || SPL_PINCTRL +config AR933X_PINCTRL + bool "QCA/Athores ar933x pin control driver" + depends on DM && SOC_AR933X + help + Support pin multiplexing control on QCA/Athores ar933x SoCs. + The driver is controlled by a device tree node which contains + both the GPIO definitions and pin control functions for each + available multiplex function. + config ROCKCHIP_PINCTRL bool "Rockchip pin control driver" depends on DM diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile index 37dc904640..b99ed2f191 100644 --- a/drivers/pinctrl/Makefile +++ b/drivers/pinctrl/Makefile @@ -6,6 +6,7 @@ obj-y += pinctrl-uclass.o obj-$(CONFIG_$(SPL_)PINCTRL_GENERIC) += pinctrl-generic.o obj-y += nxp/ +obj-$(CONFIG_ARCH_ATH79) += ath79/ obj-$(CONFIG_ARCH_ROCKCHIP) += rockchip/ obj-$(CONFIG_PINCTRL_SANDBOX) += pinctrl-sandbox.o diff --git a/drivers/pinctrl/ath79/Makefile b/drivers/pinctrl/ath79/Makefile new file mode 100644 index 0000000000..3fdcf6c4b8 --- /dev/null +++ b/drivers/pinctrl/ath79/Makefile @@ -0,0 +1,5 @@ +# +# SPDX-License-Identifier: GPL-2.0+ +# + +obj-$(CONFIG_AR933X_PINCTRL) += pinctrl_ar933x.o diff --git a/drivers/pinctrl/ath79/pinctrl_ar933x.c b/drivers/pinctrl/ath79/pinctrl_ar933x.c new file mode 100644 index 0000000000..e3f64b6355 --- /dev/null +++ b/drivers/pinctrl/ath79/pinctrl_ar933x.c @@ -0,0 +1,136 @@ +/* + * Copyright (C) 2015-2016 Wills Wang + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include +#include +#include + +DECLARE_GLOBAL_DATA_PTR; + +enum periph_id { + PERIPH_ID_UART0, + PERIPH_ID_SPI0, + PERIPH_ID_NONE = -1, +}; + +struct ar933x_pinctrl_priv { + void __iomem *regs; +}; + +static void pinctrl_ar933x_spi_config(struct ar933x_pinctrl_priv *priv, int cs) +{ + switch (cs) { + case 0: + clrsetbits_be32(priv->regs + AR71XX_GPIO_REG_OE, + AR933X_GPIO(4), AR933X_GPIO(3) | + AR933X_GPIO(5) | AR933X_GPIO(2)); + setbits_be32(priv->regs + AR71XX_GPIO_REG_FUNC, + AR933X_GPIO_FUNC_SPI_EN | + AR933X_GPIO_FUNC_RES_TRUE); + break; + } +} + +static void pinctrl_ar933x_uart_config(struct ar933x_pinctrl_priv *priv, int uart_id) +{ + switch (uart_id) { + case PERIPH_ID_UART0: + clrsetbits_be32(priv->regs + AR71XX_GPIO_REG_OE, + AR933X_GPIO(9), AR933X_GPIO(10)); + setbits_be32(priv->regs + AR71XX_GPIO_REG_FUNC, + AR933X_GPIO_FUNC_UART_EN | + AR933X_GPIO_FUNC_RES_TRUE); + break; + } +} + +static int ar933x_pinctrl_request(struct udevice *dev, int func, int flags) +{ + struct ar933x_pinctrl_priv *priv = dev_get_priv(dev); + + debug("%s: func=%x, flags=%x\n", __func__, func, flags); + switch (func) { + case PERIPH_ID_SPI0: + pinctrl_ar933x_spi_config(priv, flags); + break; + case PERIPH_ID_UART0: + pinctrl_ar933x_uart_config(priv, func); + break; + default: + return -EINVAL; + } + + return 0; +} + +static int ar933x_pinctrl_get_periph_id(struct udevice *dev, + struct udevice *periph) +{ + u32 cell[2]; + int ret; + + ret = fdtdec_get_int_array(gd->fdt_blob, periph->of_offset, + "interrupts", cell, ARRAY_SIZE(cell)); + if (ret < 0) + return -EINVAL; + + switch (cell[0]) { + case 128: + return PERIPH_ID_UART0; + case 129: + return PERIPH_ID_SPI0; + } + return -ENOENT; +} + +static int ar933x_pinctrl_set_state_simple(struct udevice *dev, + struct udevice *periph) +{ + int func; + + func = ar933x_pinctrl_get_periph_id(dev, periph); + if (func < 0) + return func; + return ar933x_pinctrl_request(dev, func, 0); +} + +static struct pinctrl_ops ar933x_pinctrl_ops = { + .set_state_simple = ar933x_pinctrl_set_state_simple, + .request = ar933x_pinctrl_request, + .get_periph_id = ar933x_pinctrl_get_periph_id, +}; + +static int ar933x_pinctrl_probe(struct udevice *dev) +{ + struct ar933x_pinctrl_priv *priv = dev_get_priv(dev); + fdt_addr_t addr; + + addr = dev_get_addr(dev); + if (addr == FDT_ADDR_T_NONE) + return -EINVAL; + + priv->regs = map_physmem(addr, + AR71XX_GPIO_SIZE, + MAP_NOCACHE); + return 0; +} + +static const struct udevice_id ar933x_pinctrl_ids[] = { + { .compatible = "qca,ar933x-pinctrl" }, + { } +}; + +U_BOOT_DRIVER(pinctrl_ar933x) = { + .name = "pinctrl_ar933x", + .id = UCLASS_PINCTRL, + .of_match = ar933x_pinctrl_ids, + .priv_auto_alloc_size = sizeof(struct ar933x_pinctrl_priv), + .ops = &ar933x_pinctrl_ops, + .probe = ar933x_pinctrl_probe, +}; -- cgit From c102453aebe92530962de41539ce4f198d27b9c7 Mon Sep 17 00:00:00 2001 From: Wills Wang Date: Wed, 16 Mar 2016 16:59:56 +0800 Subject: drivers: pinctrl: Add simple pinctrl driver for Qualcomm/Atheros qca953x. This is a simple pinctrl driver, it just support uart and spi pin-mux now. Signed-off-by: Wills Wang Reviewed-by: Simon Glass [fixed typo in commit subject line] Signed-off-by: Daniel Schwierzeck --- drivers/pinctrl/Kconfig | 9 ++ drivers/pinctrl/ath79/Makefile | 1 + drivers/pinctrl/ath79/pinctrl_qca953x.c | 156 ++++++++++++++++++++++++++++++++ 3 files changed, 166 insertions(+) create mode 100644 drivers/pinctrl/ath79/pinctrl_qca953x.c (limited to 'drivers') diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig index 854d5a500a..567b7662d0 100644 --- a/drivers/pinctrl/Kconfig +++ b/drivers/pinctrl/Kconfig @@ -114,6 +114,15 @@ config AR933X_PINCTRL both the GPIO definitions and pin control functions for each available multiplex function. +config QCA953X_PINCTRL + bool "QCA/Athores qca953x pin control driver" + depends on DM && SOC_QCA953X + help + Support pin multiplexing control on QCA/Athores qca953x SoCs. + The driver is controlled by a device tree node which contains + both the GPIO definitions and pin control functions for each + available multiplex function. + config ROCKCHIP_PINCTRL bool "Rockchip pin control driver" depends on DM diff --git a/drivers/pinctrl/ath79/Makefile b/drivers/pinctrl/ath79/Makefile index 3fdcf6c4b8..dcea10ace6 100644 --- a/drivers/pinctrl/ath79/Makefile +++ b/drivers/pinctrl/ath79/Makefile @@ -3,3 +3,4 @@ # obj-$(CONFIG_AR933X_PINCTRL) += pinctrl_ar933x.o +obj-$(CONFIG_QCA953x_PINCTRL) += pinctrl_qca953x.o diff --git a/drivers/pinctrl/ath79/pinctrl_qca953x.c b/drivers/pinctrl/ath79/pinctrl_qca953x.c new file mode 100644 index 0000000000..d02597e968 --- /dev/null +++ b/drivers/pinctrl/ath79/pinctrl_qca953x.c @@ -0,0 +1,156 @@ +/* + * Copyright (C) 2015-2016 Wills Wang + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include +#include +#include + +DECLARE_GLOBAL_DATA_PTR; + +enum periph_id { + PERIPH_ID_UART0, + PERIPH_ID_SPI0, + PERIPH_ID_NONE = -1, +}; + +struct qca953x_pinctrl_priv { + void __iomem *regs; +}; + +static void pinctrl_qca953x_spi_config(struct qca953x_pinctrl_priv *priv, int cs) +{ + switch (cs) { + case 0: + clrsetbits_be32(priv->regs + AR71XX_GPIO_REG_OE, + QCA953X_GPIO(5) | QCA953X_GPIO(6) | + QCA953X_GPIO(7), QCA953X_GPIO(8)); + + clrsetbits_be32(priv->regs + QCA953X_GPIO_REG_OUT_FUNC1, + QCA953X_GPIO_MUX_MASK(8) | + QCA953X_GPIO_MUX_MASK(16) | + QCA953X_GPIO_MUX_MASK(24), + (QCA953X_GPIO_OUT_MUX_SPI_CS0 << 8) | + (QCA953X_GPIO_OUT_MUX_SPI_CLK << 16) | + (QCA953X_GPIO_OUT_MUX_SPI_MOSI << 24)); + + clrsetbits_be32(priv->regs + QCA953X_GPIO_REG_IN_ENABLE0, + QCA953X_GPIO_MUX_MASK(0), + QCA953X_GPIO_IN_MUX_SPI_DATA_IN); + + setbits_be32(priv->regs + AR71XX_GPIO_REG_OUT, + QCA953X_GPIO(8)); + break; + } +} + +static void pinctrl_qca953x_uart_config(struct qca953x_pinctrl_priv *priv, int uart_id) +{ + switch (uart_id) { + case PERIPH_ID_UART0: + clrsetbits_be32(priv->regs + AR71XX_GPIO_REG_OE, + QCA953X_GPIO(9), QCA953X_GPIO(10)); + + clrsetbits_be32(priv->regs + QCA953X_GPIO_REG_OUT_FUNC2, + QCA953X_GPIO_MUX_MASK(16), + QCA953X_GPIO_OUT_MUX_UART0_SOUT << 16); + + clrsetbits_be32(priv->regs + QCA953X_GPIO_REG_IN_ENABLE0, + QCA953X_GPIO_MUX_MASK(8), + QCA953X_GPIO_IN_MUX_UART0_SIN << 8); + + setbits_be32(priv->regs + AR71XX_GPIO_REG_OUT, + QCA953X_GPIO(10)); + break; + } +} + +static int qca953x_pinctrl_request(struct udevice *dev, int func, int flags) +{ + struct qca953x_pinctrl_priv *priv = dev_get_priv(dev); + + debug("%s: func=%x, flags=%x\n", __func__, func, flags); + switch (func) { + case PERIPH_ID_SPI0: + pinctrl_qca953x_spi_config(priv, flags); + break; + case PERIPH_ID_UART0: + pinctrl_qca953x_uart_config(priv, func); + break; + default: + return -EINVAL; + } + + return 0; +} + +static int qca953x_pinctrl_get_periph_id(struct udevice *dev, + struct udevice *periph) +{ + u32 cell[2]; + int ret; + + ret = fdtdec_get_int_array(gd->fdt_blob, periph->of_offset, + "interrupts", cell, ARRAY_SIZE(cell)); + if (ret < 0) + return -EINVAL; + + switch (cell[0]) { + case 128: + return PERIPH_ID_UART0; + case 129: + return PERIPH_ID_SPI0; + } + return -ENOENT; +} + +static int qca953x_pinctrl_set_state_simple(struct udevice *dev, + struct udevice *periph) +{ + int func; + + func = qca953x_pinctrl_get_periph_id(dev, periph); + if (func < 0) + return func; + return qca953x_pinctrl_request(dev, func, 0); +} + +static struct pinctrl_ops qca953x_pinctrl_ops = { + .set_state_simple = qca953x_pinctrl_set_state_simple, + .request = qca953x_pinctrl_request, + .get_periph_id = qca953x_pinctrl_get_periph_id, +}; + +static int qca953x_pinctrl_probe(struct udevice *dev) +{ + struct qca953x_pinctrl_priv *priv = dev_get_priv(dev); + fdt_addr_t addr; + + addr = dev_get_addr(dev); + if (addr == FDT_ADDR_T_NONE) + return -EINVAL; + + priv->regs = map_physmem(addr, + AR71XX_GPIO_SIZE, + MAP_NOCACHE); + return 0; +} + +static const struct udevice_id qca953x_pinctrl_ids[] = { + { .compatible = "qca,qca953x-pinctrl" }, + { } +}; + +U_BOOT_DRIVER(pinctrl_qca953x) = { + .name = "pinctrl_qca953x", + .id = UCLASS_PINCTRL, + .of_match = qca953x_pinctrl_ids, + .priv_auto_alloc_size = sizeof(struct qca953x_pinctrl_priv), + .ops = &qca953x_pinctrl_ops, + .probe = qca953x_pinctrl_probe, +}; -- cgit From 60b49761e9d2f0d16ac5cef934504bc895ac3913 Mon Sep 17 00:00:00 2001 From: Wills Wang Date: Wed, 16 Mar 2016 16:59:57 +0800 Subject: drivers: serial: add serial driver for ar933x SOC This patch add support for ar933x serial. Signed-off-by: Wills Wang Reviewed-by: Thomas Chou Reviewed-by: Daniel Schwierzeck Reviewed-by: Simon Glass --- drivers/serial/Kconfig | 18 +++ drivers/serial/Makefile | 1 + drivers/serial/serial_ar933x.c | 255 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 274 insertions(+) create mode 100644 drivers/serial/serial_ar933x.c (limited to 'drivers') diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index a9a5d475dd..2497ae90a0 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig @@ -89,6 +89,15 @@ config DEBUG_UART_ALTERA_UART You will need to provide parameters to make this work. The driver will be available until the real driver model serial is running. +config DEBUG_UART_AR933X + bool "QCA/Atheros ar933x" + depends on AR933X_UART + help + Select this to enable a debug UART using the ar933x uart driver. + You will need to provide parameters to make this work. The + driver will be available until the real driver model serial is + running. + config DEBUG_UART_NS16550 bool "ns16550" help @@ -263,6 +272,15 @@ config ALTERA_UART Select this to enable an UART for Altera devices. Please find details on the "Embedded Peripherals IP User Guide" of Altera. +config AR933X_UART + bool "QCA/Atheros ar933x UART support" + depends on DM_SERIAL && SOC_AR933X + help + Select this to enable UART support for QCA/Atheros ar933x + devices. This driver uses driver model and requires a device + tree binding to operate, please refer to the document at + doc/device-tree-bindings/serial/qca,ar9330-uart.txt. + config FSL_LPUART bool "Freescale LPUART support" help diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile index b0ac9d8a56..9def128e89 100644 --- a/drivers/serial/Makefile +++ b/drivers/serial/Makefile @@ -17,6 +17,7 @@ endif obj-$(CONFIG_ALTERA_UART) += altera_uart.o obj-$(CONFIG_ALTERA_JTAG_UART) += altera_jtag_uart.o +obj-$(CONFIG_AR933X_UART) += serial_ar933x.o obj-$(CONFIG_ARM_DCC) += arm_dcc.o obj-$(CONFIG_ATMEL_USART) += atmel_usart.o obj-$(CONFIG_EFI_APP) += serial_efi.o diff --git a/drivers/serial/serial_ar933x.c b/drivers/serial/serial_ar933x.c new file mode 100644 index 0000000000..d43f9c97d7 --- /dev/null +++ b/drivers/serial/serial_ar933x.c @@ -0,0 +1,255 @@ +/* + * Copyright (C) 2015-2016 Wills Wang + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define AR933X_UART_DATA_REG 0x00 +#define AR933X_UART_CS_REG 0x04 +#define AR933X_UART_CLK_REG 0x08 + +#define AR933X_UART_DATA_TX_RX_MASK 0xff +#define AR933X_UART_DATA_RX_CSR BIT(8) +#define AR933X_UART_DATA_TX_CSR BIT(9) +#define AR933X_UART_CS_IF_MODE_S 2 +#define AR933X_UART_CS_IF_MODE_M 0x3 +#define AR933X_UART_CS_IF_MODE_DTE 1 +#define AR933X_UART_CS_IF_MODE_DCE 2 +#define AR933X_UART_CS_TX_RDY_ORIDE BIT(7) +#define AR933X_UART_CS_RX_RDY_ORIDE BIT(8) +#define AR933X_UART_CLK_STEP_M 0xffff +#define AR933X_UART_CLK_SCALE_M 0xfff +#define AR933X_UART_CLK_SCALE_S 16 +#define AR933X_UART_CLK_STEP_S 0 + +struct ar933x_serial_priv { + void __iomem *regs; +}; + +/* + * baudrate = (clk / (scale + 1)) * (step * (1 / 2^17)) + */ +static u32 ar933x_serial_get_baud(u32 clk, u32 scale, u32 step) +{ + u64 t; + u32 div; + + div = (2 << 16) * (scale + 1); + t = clk; + t *= step; + t += (div / 2); + do_div(t, div); + + return t; +} + +static void ar933x_serial_get_scale_step(u32 clk, u32 baud, + u32 *scale, u32 *step) +{ + u32 tscale, baudrate; + long min_diff; + + *scale = 0; + *step = 0; + + min_diff = baud; + for (tscale = 0; tscale < AR933X_UART_CLK_SCALE_M; tscale++) { + u64 tstep; + int diff; + + tstep = baud * (tscale + 1); + tstep *= (2 << 16); + do_div(tstep, clk); + + if (tstep > AR933X_UART_CLK_STEP_M) + break; + + baudrate = ar933x_serial_get_baud(clk, tscale, tstep); + diff = abs(baudrate - baud); + if (diff < min_diff) { + min_diff = diff; + *scale = tscale; + *step = tstep; + } + } +} + +static int ar933x_serial_setbrg(struct udevice *dev, int baudrate) +{ + struct ar933x_serial_priv *priv = dev_get_priv(dev); + u32 val, scale, step; + + val = get_serial_clock(); + ar933x_serial_get_scale_step(val, baudrate, &scale, &step); + + val = (scale & AR933X_UART_CLK_SCALE_M) + << AR933X_UART_CLK_SCALE_S; + val |= (step & AR933X_UART_CLK_STEP_M) + << AR933X_UART_CLK_STEP_S; + writel(val, priv->regs + AR933X_UART_CLK_REG); + + return 0; +} + +static int ar933x_serial_putc(struct udevice *dev, const char c) +{ + struct ar933x_serial_priv *priv = dev_get_priv(dev); + u32 data; + + data = readl(priv->regs + AR933X_UART_DATA_REG); + if (!(data & AR933X_UART_DATA_TX_CSR)) + return -EAGAIN; + + data = (u32)c | AR933X_UART_DATA_TX_CSR; + writel(data, priv->regs + AR933X_UART_DATA_REG); + + return 0; +} + +static int ar933x_serial_getc(struct udevice *dev) +{ + struct ar933x_serial_priv *priv = dev_get_priv(dev); + u32 data; + + data = readl(priv->regs + AR933X_UART_DATA_REG); + if (!(data & AR933X_UART_DATA_RX_CSR)) + return -EAGAIN; + + writel(AR933X_UART_DATA_RX_CSR, priv->regs + AR933X_UART_DATA_REG); + return data & AR933X_UART_DATA_TX_RX_MASK; +} + +static int ar933x_serial_pending(struct udevice *dev, bool input) +{ + struct ar933x_serial_priv *priv = dev_get_priv(dev); + u32 data; + + data = readl(priv->regs + AR933X_UART_DATA_REG); + if (input) + return (data & AR933X_UART_DATA_RX_CSR) ? 1 : 0; + else + return (data & AR933X_UART_DATA_TX_CSR) ? 0 : 1; +} + +static int ar933x_serial_probe(struct udevice *dev) +{ + struct ar933x_serial_priv *priv = dev_get_priv(dev); + struct udevice *pinctrl; + fdt_addr_t addr; + u32 val; + int ret; + + ret = uclass_get_device(UCLASS_PINCTRL, 0, &pinctrl); + if (ret) + return ret; + ret = pinctrl_get_periph_id(pinctrl, dev); + if (ret < 0) + return ret; + ret = pinctrl_request(pinctrl, ret, 0); + if (ret < 0) + return ret; + + addr = dev_get_addr(dev); + if (addr == FDT_ADDR_T_NONE) + return -EINVAL; + + priv->regs = map_physmem(addr, + AR933X_UART_SIZE, + MAP_NOCACHE); + + /* + * UART controller configuration: + * - no DMA + * - no interrupt + * - DCE mode + * - no flow control + * - set RX ready oride + * - set TX ready oride + */ + val = (AR933X_UART_CS_IF_MODE_DCE << AR933X_UART_CS_IF_MODE_S) | + AR933X_UART_CS_TX_RDY_ORIDE | AR933X_UART_CS_RX_RDY_ORIDE; + writel(val, priv->regs + AR933X_UART_CS_REG); + return 0; +} + +static const struct dm_serial_ops ar933x_serial_ops = { + .putc = ar933x_serial_putc, + .pending = ar933x_serial_pending, + .getc = ar933x_serial_getc, + .setbrg = ar933x_serial_setbrg, +}; + +static const struct udevice_id ar933x_serial_ids[] = { + { .compatible = "qca,ar9330-uart" }, + { } +}; + +U_BOOT_DRIVER(serial_ar933x) = { + .name = "serial_ar933x", + .id = UCLASS_SERIAL, + .of_match = ar933x_serial_ids, + .priv_auto_alloc_size = sizeof(struct ar933x_serial_priv), + .probe = ar933x_serial_probe, + .ops = &ar933x_serial_ops, + .flags = DM_FLAG_PRE_RELOC, +}; + +#ifdef CONFIG_DEBUG_UART_AR933X + +#include + +static inline void _debug_uart_init(void) +{ + void __iomem *regs = (void *)CONFIG_DEBUG_UART_BASE; + u32 val, scale, step; + + /* + * UART controller configuration: + * - no DMA + * - no interrupt + * - DCE mode + * - no flow control + * - set RX ready oride + * - set TX ready oride + */ + val = (AR933X_UART_CS_IF_MODE_DCE << AR933X_UART_CS_IF_MODE_S) | + AR933X_UART_CS_TX_RDY_ORIDE | AR933X_UART_CS_RX_RDY_ORIDE; + writel(val, regs + AR933X_UART_CS_REG); + + ar933x_serial_get_scale_step(CONFIG_DEBUG_UART_CLOCK, + CONFIG_BAUDRATE, &scale, &step); + + val = (scale & AR933X_UART_CLK_SCALE_M) + << AR933X_UART_CLK_SCALE_S; + val |= (step & AR933X_UART_CLK_STEP_M) + << AR933X_UART_CLK_STEP_S; + writel(val, regs + AR933X_UART_CLK_REG); +} + +static inline void _debug_uart_putc(int c) +{ + void __iomem *regs = (void *)CONFIG_DEBUG_UART_BASE; + u32 data; + + do { + data = readl(regs + AR933X_UART_DATA_REG); + } while (!(data & AR933X_UART_DATA_TX_CSR)); + + data = (u32)c | AR933X_UART_DATA_TX_CSR; + writel(data, regs + AR933X_UART_DATA_REG); +} + +DEBUG_UART_FUNCS + +#endif -- cgit From b85dc4607268ffc49af642ab702d44c8b5ef3719 Mon Sep 17 00:00:00 2001 From: Wills Wang Date: Wed, 16 Mar 2016 16:59:58 +0800 Subject: drivers: spi: add spi support for QCA/Atheros ath79 SOCs This patch add a compatible spi driver for ath79 series SOC. Signed-off-by: Wills Wang Reviewed-by: Thomas Chou Reviewed-by: Daniel Schwierzeck --- drivers/spi/Kconfig | 9 ++ drivers/spi/Makefile | 1 + drivers/spi/ath79_spi.c | 240 ++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 250 insertions(+) create mode 100644 drivers/spi/ath79_spi.c (limited to 'drivers') diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index f0258f84af..b7fd8e53a2 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -23,6 +23,15 @@ config ALTERA_SPI IP core. Please find details on the "Embedded Peripherals IP User Guide" of Altera. +config ATH79_SPI + bool "Atheros SPI driver" + depends on ARCH_ATH79 + help + Enable the Atheros ar7xxx/ar9xxx SoC SPI driver, it was used + to access SPI NOR flash and other SPI peripherals. This driver + uses driver model and requires a device tree binding to operate. + please refer to doc/device-tree-bindings/spi/spi-ath79.txt. + config CADENCE_QSPI bool "Cadence QSPI driver" help diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile index 3eca7456d6..7fb2926e78 100644 --- a/drivers/spi/Makefile +++ b/drivers/spi/Makefile @@ -17,6 +17,7 @@ endif obj-$(CONFIG_ALTERA_SPI) += altera_spi.o obj-$(CONFIG_ARMADA100_SPI) += armada100_spi.o +obj-$(CONFIG_ATH79_SPI) += ath79_spi.o obj-$(CONFIG_ATMEL_DATAFLASH_SPI) += atmel_dataflash_spi.o obj-$(CONFIG_ATMEL_SPI) += atmel_spi.o obj-$(CONFIG_BFIN_SPI) += bfin_spi.o diff --git a/drivers/spi/ath79_spi.c b/drivers/spi/ath79_spi.c new file mode 100644 index 0000000000..0c1022da05 --- /dev/null +++ b/drivers/spi/ath79_spi.c @@ -0,0 +1,240 @@ +/* + * Copyright (C) 2015-2016 Wills Wang + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* CLOCK_DIVIDER = 3 (SPI clock = 200 / 8 ~ 25 MHz) */ +#define ATH79_SPI_CLK_DIV(x) (((x) >> 1) - 1) +#define ATH79_SPI_RRW_DELAY_FACTOR 12000 +#define ATH79_SPI_MHZ (1000 * 1000) + +struct ath79_spi_priv { + void __iomem *regs; + u32 rrw_delay; +}; + +static void spi_cs_activate(struct udevice *dev) +{ + struct udevice *bus = dev_get_parent(dev); + struct ath79_spi_priv *priv = dev_get_priv(bus); + + writel(AR71XX_SPI_FS_GPIO, priv->regs + AR71XX_SPI_REG_FS); + writel(AR71XX_SPI_IOC_CS_ALL, priv->regs + AR71XX_SPI_REG_IOC); +} + +static void spi_cs_deactivate(struct udevice *dev) +{ + struct udevice *bus = dev_get_parent(dev); + struct ath79_spi_priv *priv = dev_get_priv(bus); + + writel(AR71XX_SPI_IOC_CS_ALL, priv->regs + AR71XX_SPI_REG_IOC); + writel(0, priv->regs + AR71XX_SPI_REG_FS); +} + +static int ath79_spi_claim_bus(struct udevice *dev) +{ + return 0; +} + +static int ath79_spi_release_bus(struct udevice *dev) +{ + return 0; +} + +static int ath79_spi_xfer(struct udevice *dev, unsigned int bitlen, + const void *dout, void *din, unsigned long flags) +{ + struct udevice *bus = dev_get_parent(dev); + struct ath79_spi_priv *priv = dev_get_priv(bus); + struct dm_spi_slave_platdata *slave = dev_get_parent_platdata(dev); + u8 *rx = din; + const u8 *tx = dout; + u8 curbyte, curbitlen, restbits; + u32 bytes = bitlen / 8; + u32 out, in; + u64 tick; + + if (flags & SPI_XFER_BEGIN) + spi_cs_activate(dev); + + restbits = (bitlen % 8); + if (restbits) + bytes++; + + out = AR71XX_SPI_IOC_CS_ALL & ~(AR71XX_SPI_IOC_CS(slave->cs)); + while (bytes > 0) { + bytes--; + curbyte = 0; + if (tx) + curbyte = *tx++; + + if (restbits && !bytes) { + curbitlen = restbits; + curbyte <<= 8 - restbits; + } else { + curbitlen = 8; + } + + for (curbyte <<= (8 - curbitlen); curbitlen; curbitlen--) { + if (curbyte & 0x80) + out |= AR71XX_SPI_IOC_DO; + else + out &= ~(AR71XX_SPI_IOC_DO); + + writel(out, priv->regs + AR71XX_SPI_REG_IOC); + + /* delay for low level */ + if (priv->rrw_delay) { + tick = get_ticks() + priv->rrw_delay; + while (get_ticks() < tick) + /*NOP*/; + } + + writel(out | AR71XX_SPI_IOC_CLK, + priv->regs + AR71XX_SPI_REG_IOC); + + /* delay for high level */ + if (priv->rrw_delay) { + tick = get_ticks() + priv->rrw_delay; + while (get_ticks() < tick) + /*NOP*/; + } + + curbyte <<= 1; + } + + if (!bytes) + writel(out, priv->regs + AR71XX_SPI_REG_IOC); + + in = readl(priv->regs + AR71XX_SPI_REG_RDS); + if (rx) { + if (restbits && !bytes) + *rx++ = (in << (8 - restbits)); + else + *rx++ = in; + } + } + + if (flags & SPI_XFER_END) + spi_cs_deactivate(dev); + + return 0; +} + + +static int ath79_spi_set_speed(struct udevice *bus, uint speed) +{ + struct ath79_spi_priv *priv = dev_get_priv(bus); + u32 val, div = 0; + u64 time; + + if (speed) + div = get_bus_freq(0) / speed; + + if (div > 63) + div = 63; + + if (div < 5) + div = 5; + + /* calculate delay */ + time = get_tbclk(); + do_div(time, speed / 2); + val = get_bus_freq(0) / ATH79_SPI_MHZ; + val = ATH79_SPI_RRW_DELAY_FACTOR / val; + if (time > val) + priv->rrw_delay = time - val + 1; + else + priv->rrw_delay = 0; + + writel(AR71XX_SPI_FS_GPIO, priv->regs + AR71XX_SPI_REG_FS); + clrsetbits_be32(priv->regs + AR71XX_SPI_REG_CTRL, + AR71XX_SPI_CTRL_DIV_MASK, + ATH79_SPI_CLK_DIV(div)); + writel(0, priv->regs + AR71XX_SPI_REG_FS); + return 0; +} + +static int ath79_spi_set_mode(struct udevice *bus, uint mode) +{ + return 0; +} + +static int ath79_spi_probe(struct udevice *bus) +{ + struct ath79_spi_priv *priv = dev_get_priv(bus); + struct udevice *pinctrl; + fdt_addr_t addr; + int ret; + + ret = uclass_get_device(UCLASS_PINCTRL, 0, &pinctrl); + if (ret) + return ret; + ret = pinctrl_get_periph_id(pinctrl, bus); + if (ret < 0) + return ret; + ret = pinctrl_request(pinctrl, ret, 0); + if (ret < 0) + return ret; + + addr = dev_get_addr(bus); + if (addr == FDT_ADDR_T_NONE) + return -EINVAL; + + priv->regs = map_physmem(addr, + AR71XX_SPI_SIZE, + MAP_NOCACHE); + + /* Init SPI Hardware, disable remap, set clock */ + writel(AR71XX_SPI_FS_GPIO, priv->regs + AR71XX_SPI_REG_FS); + writel(AR71XX_SPI_CTRL_RD | ATH79_SPI_CLK_DIV(8), + priv->regs + AR71XX_SPI_REG_CTRL); + writel(0, priv->regs + AR71XX_SPI_REG_FS); + + return 0; +} + +static int ath79_cs_info(struct udevice *bus, uint cs, + struct spi_cs_info *info) +{ + /* Always allow activity on CS 0/1/2 */ + if (cs >= 3) + return -ENODEV; + + return 0; +} + +static const struct dm_spi_ops ath79_spi_ops = { + .claim_bus = ath79_spi_claim_bus, + .release_bus = ath79_spi_release_bus, + .xfer = ath79_spi_xfer, + .set_speed = ath79_spi_set_speed, + .set_mode = ath79_spi_set_mode, + .cs_info = ath79_cs_info, +}; + +static const struct udevice_id ath79_spi_ids[] = { + { .compatible = "qca,ar7100-spi" }, + {} +}; + +U_BOOT_DRIVER(ath79_spi) = { + .name = "ath79_spi", + .id = UCLASS_SPI, + .of_match = ath79_spi_ids, + .ops = &ath79_spi_ops, + .priv_auto_alloc_size = sizeof(struct ath79_spi_priv), + .probe = ath79_spi_probe, +}; -- cgit From 5c990456999c5672b8e626f945b0e8e17162e02f Mon Sep 17 00:00:00 2001 From: Purna Chandra Mandal Date: Fri, 18 Mar 2016 18:36:08 +0530 Subject: drivers: mtd: add Microchip PIC32 internal non-CFI flash driver. PIC32 internal flash devices are parallel NOR flash divided into number of banks to allow erase-programming in one while fetch and execution continues on other. As the flash banks are memory mapped stored code can be executed directly from flash (XIP), also there is additional hardware logic to prefetch and cache contents to improve execution performance. These flash can also be used to store user data (like environment). Flash erase and programming are handled by on-chip NVM controller. Driver implemented driver model but MTD is not really support. Signed-off-by: Purna Chandra Mandal Reviewed-by: Simon Glass --- drivers/mtd/Kconfig | 7 + drivers/mtd/Makefile | 1 + drivers/mtd/pic32_flash.c | 444 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 452 insertions(+) create mode 100644 drivers/mtd/pic32_flash.c (limited to 'drivers') diff --git a/drivers/mtd/Kconfig b/drivers/mtd/Kconfig index c58841e7d8..390e9e4ea3 100644 --- a/drivers/mtd/Kconfig +++ b/drivers/mtd/Kconfig @@ -28,6 +28,13 @@ config ALTERA_QSPI NOR flash to parallel flash interface. Please find details on the "Embedded Peripherals IP User Guide" of Altera. +config FLASH_PIC32 + bool "Microchip PIC32 Flash driver" + depends on MACH_PIC32 && MTD + help + This enables access to Microchip PIC32 internal non-CFI flash + chips through PIC32 Non-Volatile-Memory Controller. + endmenu source "drivers/mtd/nand/Kconfig" diff --git a/drivers/mtd/Makefile b/drivers/mtd/Makefile index 703700aae0..bd680a784f 100644 --- a/drivers/mtd/Makefile +++ b/drivers/mtd/Makefile @@ -19,5 +19,6 @@ obj-$(CONFIG_HAS_DATAFLASH) += dataflash.o obj-$(CONFIG_FTSMC020) += ftsmc020.o obj-$(CONFIG_FLASH_CFI_LEGACY) += jedec_flash.o obj-$(CONFIG_MW_EEPROM) += mw_eeprom.o +obj-$(CONFIG_FLASH_PIC32) += pic32_flash.o obj-$(CONFIG_ST_SMI) += st_smi.o obj-$(CONFIG_STM32_FLASH) += stm32_flash.o diff --git a/drivers/mtd/pic32_flash.c b/drivers/mtd/pic32_flash.c new file mode 100644 index 0000000000..9166fcd980 --- /dev/null +++ b/drivers/mtd/pic32_flash.c @@ -0,0 +1,444 @@ +/* + * Copyright (C) 2015 + * Cristian Birsan + * Purna Chandra Mandal + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include +#include +#include + +DECLARE_GLOBAL_DATA_PTR; + +/* NVM Controller registers */ +struct pic32_reg_nvm { + struct pic32_reg_atomic ctrl; + struct pic32_reg_atomic key; + struct pic32_reg_atomic addr; + struct pic32_reg_atomic data; +}; + +/* NVM operations */ +#define NVMOP_NOP 0 +#define NVMOP_WORD_WRITE 1 +#define NVMOP_PAGE_ERASE 4 + +/* NVM control bits */ +#define NVM_WR BIT(15) +#define NVM_WREN BIT(14) +#define NVM_WRERR BIT(13) +#define NVM_LVDERR BIT(12) + +/* NVM programming unlock register */ +#define LOCK_KEY 0x0 +#define UNLOCK_KEY1 0xaa996655 +#define UNLOCK_KEY2 0x556699aa + +/* + * PIC32 flash banks consist of number of pages, each page + * into number of rows and rows into number of words. + * Here we will maintain page information instead of sector. + */ +flash_info_t flash_info[CONFIG_SYS_MAX_FLASH_BANKS]; +static struct pic32_reg_nvm *nvm_regs_p; + +static inline void flash_initiate_operation(u32 nvmop) +{ + /* set operation */ + writel(nvmop, &nvm_regs_p->ctrl.raw); + + /* enable flash write */ + writel(NVM_WREN, &nvm_regs_p->ctrl.set); + + /* unlock sequence */ + writel(LOCK_KEY, &nvm_regs_p->key.raw); + writel(UNLOCK_KEY1, &nvm_regs_p->key.raw); + writel(UNLOCK_KEY2, &nvm_regs_p->key.raw); + + /* initiate operation */ + writel(NVM_WR, &nvm_regs_p->ctrl.set); +} + +static int flash_wait_till_busy(const char *func, ulong timeout) +{ + int ret = wait_for_bit(__func__, &nvm_regs_p->ctrl.raw, + NVM_WR, false, timeout, false); + + return ret ? ERR_TIMOUT : ERR_OK; +} + +static inline int flash_complete_operation(void) +{ + u32 tmp; + + tmp = readl(&nvm_regs_p->ctrl.raw); + if (tmp & NVM_WRERR) { + printf("Error in Block Erase - Lock Bit may be set!\n"); + flash_initiate_operation(NVMOP_NOP); + return ERR_PROTECTED; + } + + if (tmp & NVM_LVDERR) { + printf("Error in Block Erase - low-vol detected!\n"); + flash_initiate_operation(NVMOP_NOP); + return ERR_NOT_ERASED; + } + + /* disable flash write or erase operation */ + writel(NVM_WREN, &nvm_regs_p->ctrl.clr); + + return ERR_OK; +} + +/* + * Erase flash sectors, returns: + * ERR_OK - OK + * ERR_INVAL - invalid sector arguments + * ERR_TIMOUT - write timeout + * ERR_NOT_ERASED - Flash not erased + * ERR_UNKNOWN_FLASH_VENDOR - incorrect flash + */ +int flash_erase(flash_info_t *info, int s_first, int s_last) +{ + ulong sect_start, sect_end, flags; + int prot, sect; + int rc; + + if ((info->flash_id & FLASH_VENDMASK) != FLASH_MAN_MCHP) { + printf("Can't erase unknown flash type %08lx - aborted\n", + info->flash_id); + return ERR_UNKNOWN_FLASH_VENDOR; + } + + if ((s_first < 0) || (s_first > s_last)) { + printf("- no sectors to erase\n"); + return ERR_INVAL; + } + + prot = 0; + for (sect = s_first; sect <= s_last; ++sect) { + if (info->protect[sect]) + prot++; + } + + if (prot) + printf("- Warning: %d protected sectors will not be erased!\n", + prot); + else + printf("\n"); + + /* erase on unprotected sectors */ + for (sect = s_first; sect <= s_last; sect++) { + if (info->protect[sect]) + continue; + + /* disable interrupts */ + flags = disable_interrupts(); + + /* write destination page address (physical) */ + sect_start = CPHYSADDR(info->start[sect]); + writel(sect_start, &nvm_regs_p->addr.raw); + + /* page erase */ + flash_initiate_operation(NVMOP_PAGE_ERASE); + + /* wait */ + rc = flash_wait_till_busy(__func__, + CONFIG_SYS_FLASH_ERASE_TOUT); + + /* re-enable interrupts if necessary */ + if (flags) + enable_interrupts(); + + if (rc != ERR_OK) + return rc; + + rc = flash_complete_operation(); + if (rc != ERR_OK) + return rc; + + /* + * flash content is updated but cache might contain stale + * data, so invalidate dcache. + */ + sect_end = info->start[sect] + info->size / info->sector_count; + invalidate_dcache_range(info->start[sect], sect_end); + } + + printf(" done\n"); + return ERR_OK; +} + +int page_erase(flash_info_t *info, int sect) +{ + return 0; +} + +/* Write a word to flash */ +static int write_word(flash_info_t *info, ulong dest, ulong word) +{ + ulong flags; + int rc; + + /* read flash to check if it is sufficiently erased */ + if ((readl((void __iomem *)dest) & word) != word) { + printf("Error, Flash not erased!\n"); + return ERR_NOT_ERASED; + } + + /* disable interrupts */ + flags = disable_interrupts(); + + /* update destination page address (physical) */ + writel(CPHYSADDR(dest), &nvm_regs_p->addr.raw); + writel(word, &nvm_regs_p->data.raw); + + /* word write */ + flash_initiate_operation(NVMOP_WORD_WRITE); + + /* wait for operation to complete */ + rc = flash_wait_till_busy(__func__, CONFIG_SYS_FLASH_WRITE_TOUT); + + /* re-enable interrupts if necessary */ + if (flags) + enable_interrupts(); + + if (rc != ERR_OK) + return rc; + + return flash_complete_operation(); +} + +/* + * Copy memory to flash, returns: + * ERR_OK - OK + * ERR_TIMOUT - write timeout + * ERR_NOT_ERASED - Flash not erased + */ +int write_buff(flash_info_t *info, uchar *src, ulong addr, ulong cnt) +{ + ulong dst, tmp_le, len = cnt; + int i, l, rc; + uchar *cp; + + /* get lower word aligned address */ + dst = (addr & ~3); + + /* handle unaligned start bytes */ + l = addr - dst; + if (l != 0) { + tmp_le = 0; + for (i = 0, cp = (uchar *)dst; i < l; ++i, ++cp) + tmp_le |= *cp << (i * 8); + + for (; (i < 4) && (cnt > 0); ++i, ++src, --cnt, ++cp) + tmp_le |= *src << (i * 8); + + for (; (cnt == 0) && (i < 4); ++i, ++cp) + tmp_le |= *cp << (i * 8); + + rc = write_word(info, dst, tmp_le); + if (rc) + goto out; + + dst += 4; + } + + /* handle word aligned part */ + while (cnt >= 4) { + tmp_le = src[0] | src[1] << 8 | src[2] << 16 | src[3] << 24; + rc = write_word(info, dst, tmp_le); + if (rc) + goto out; + src += 4; + dst += 4; + cnt -= 4; + } + + if (cnt == 0) { + rc = ERR_OK; + goto out; + } + + /* handle unaligned tail bytes */ + tmp_le = 0; + for (i = 0, cp = (uchar *)dst; (i < 4) && (cnt > 0); ++i, ++cp) { + tmp_le |= *src++ << (i * 8); + --cnt; + } + + for (; i < 4; ++i, ++cp) + tmp_le |= *cp << (i * 8); + + rc = write_word(info, dst, tmp_le); +out: + /* + * flash content updated by nvm controller but CPU cache might + * have stale data, so invalidate dcache. + */ + invalidate_dcache_range(addr, addr + len); + + printf(" done\n"); + return rc; +} + +void flash_print_info(flash_info_t *info) +{ + int i; + + if (info->flash_id == FLASH_UNKNOWN) { + printf("missing or unknown FLASH type\n"); + return; + } + + switch (info->flash_id & FLASH_VENDMASK) { + case FLASH_MAN_MCHP: + printf("Microchip Technology "); + break; + default: + printf("Unknown Vendor "); + break; + } + + switch (info->flash_id & FLASH_TYPEMASK) { + case FLASH_MCHP100T: + printf("Internal (8 Mbit, 64 x 16k)\n"); + break; + default: + printf("Unknown Chip Type\n"); + break; + } + + printf(" Size: %ld MB in %d Sectors\n", + info->size >> 20, info->sector_count); + + printf(" Sector Start Addresses:"); + for (i = 0; i < info->sector_count; ++i) { + if ((i % 5) == 0) + printf("\n "); + + printf(" %08lX%s", info->start[i], + info->protect[i] ? " (RO)" : " "); + } + printf("\n"); +} + +unsigned long flash_init(void) +{ + unsigned long size = 0; + struct udevice *dev; + int bank; + + /* probe every MTD device */ + for (uclass_first_device(UCLASS_MTD, &dev); dev; + uclass_next_device(&dev)) { + /* nop */ + } + + /* calc total flash size */ + for (bank = 0; bank < CONFIG_SYS_MAX_FLASH_BANKS; ++bank) + size += flash_info[bank].size; + + return size; +} + +static void pic32_flash_bank_init(flash_info_t *info, + ulong base, ulong size) +{ + ulong sect_size; + int sect; + + /* device & manufacturer code */ + info->flash_id = FLASH_MAN_MCHP | FLASH_MCHP100T; + info->sector_count = CONFIG_SYS_MAX_FLASH_SECT; + info->size = size; + + /* update sector (i.e page) info */ + sect_size = info->size / info->sector_count; + for (sect = 0; sect < info->sector_count; sect++) { + info->start[sect] = base; + /* protect each sector by default */ + info->protect[sect] = 1; + base += sect_size; + } +} + +static int pic32_flash_probe(struct udevice *dev) +{ + void *blob = (void *)gd->fdt_blob; + int node = dev->of_offset; + const char *list, *end; + const fdt32_t *cell; + unsigned long addr, size; + int parent, addrc, sizec; + flash_info_t *info; + int len, idx; + + /* + * decode regs. there are multiple reg tuples, and they need to + * match with reg-names. + */ + parent = fdt_parent_offset(blob, node); + of_bus_default_count_cells(blob, parent, &addrc, &sizec); + list = fdt_getprop(blob, node, "reg-names", &len); + if (!list) + return -ENOENT; + + end = list + len; + cell = fdt_getprop(blob, node, "reg", &len); + if (!cell) + return -ENOENT; + + for (idx = 0, info = &flash_info[0]; list < end;) { + addr = fdt_translate_address((void *)blob, node, cell + idx); + size = fdt_addr_to_cpu(cell[idx + addrc]); + len = strlen(list); + if (!strncmp(list, "nvm", len)) { + /* NVM controller */ + nvm_regs_p = ioremap(addr, size); + } else if (!strncmp(list, "bank", 4)) { + /* Flash bank: use kseg0 cached address */ + pic32_flash_bank_init(info, CKSEG0ADDR(addr), size); + info++; + } + idx += addrc + sizec; + list += len + 1; + } + + /* disable flash write/erase operations */ + writel(NVM_WREN, &nvm_regs_p->ctrl.clr); + +#if (CONFIG_SYS_MONITOR_BASE >= CONFIG_SYS_FLASH_BASE) + /* monitor protection ON by default */ + flash_protect(FLAG_PROTECT_SET, + CONFIG_SYS_MONITOR_BASE, + CONFIG_SYS_MONITOR_BASE + monitor_flash_len - 1, + &flash_info[0]); +#endif + +#ifdef CONFIG_ENV_IS_IN_FLASH + /* ENV protection ON by default */ + flash_protect(FLAG_PROTECT_SET, + CONFIG_ENV_ADDR, + CONFIG_ENV_ADDR + CONFIG_ENV_SECT_SIZE - 1, + &flash_info[0]); +#endif + return 0; +} + +static const struct udevice_id pic32_flash_ids[] = { + { .compatible = "microchip,pic32mzda-flash" }, + {} +}; + +U_BOOT_DRIVER(pic32_flash) = { + .name = "pic32_flash", + .id = UCLASS_MTD, + .of_match = pic32_flash_ids, + .probe = pic32_flash_probe, +}; -- cgit From 5fabf2e7da1b738c6e0353b6a5a17b1a77ecc2e9 Mon Sep 17 00:00:00 2001 From: Wills Wang Date: Tue, 12 Apr 2016 11:09:18 +0800 Subject: ath79: spi: Remove the explicit pinctrl setting The correct pinctrl is handled automatically so we don't need to do it in the driver. Signed-off-by: Wills Wang --- drivers/spi/ath79_spi.c | 12 ------------ 1 file changed, 12 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/ath79_spi.c b/drivers/spi/ath79_spi.c index 0c1022da05..b18c733b67 100644 --- a/drivers/spi/ath79_spi.c +++ b/drivers/spi/ath79_spi.c @@ -175,19 +175,7 @@ static int ath79_spi_set_mode(struct udevice *bus, uint mode) static int ath79_spi_probe(struct udevice *bus) { struct ath79_spi_priv *priv = dev_get_priv(bus); - struct udevice *pinctrl; fdt_addr_t addr; - int ret; - - ret = uclass_get_device(UCLASS_PINCTRL, 0, &pinctrl); - if (ret) - return ret; - ret = pinctrl_get_periph_id(pinctrl, bus); - if (ret < 0) - return ret; - ret = pinctrl_request(pinctrl, ret, 0); - if (ret < 0) - return ret; addr = dev_get_addr(bus); if (addr == FDT_ADDR_T_NONE) -- cgit From 773f3b25384363d53e457f1faae77c91db76e0c4 Mon Sep 17 00:00:00 2001 From: Wills Wang Date: Tue, 12 Apr 2016 11:09:19 +0800 Subject: ar933x: serial: Remove the explicit pinctrl setting The correct pinctrl is handled automatically so we don't need to do it in the driver. Signed-off-by: Wills Wang --- drivers/serial/serial_ar933x.c | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/serial/serial_ar933x.c b/drivers/serial/serial_ar933x.c index d43f9c97d7..aae66dc682 100644 --- a/drivers/serial/serial_ar933x.c +++ b/drivers/serial/serial_ar933x.c @@ -38,6 +38,7 @@ struct ar933x_serial_priv { }; /* + * Baudrate algorithm come from Linux/drivers/tty/serial/ar933x_uart.c * baudrate = (clk / (scale + 1)) * (step * (1 / 2^17)) */ static u32 ar933x_serial_get_baud(u32 clk, u32 scale, u32 step) @@ -145,27 +146,14 @@ static int ar933x_serial_pending(struct udevice *dev, bool input) static int ar933x_serial_probe(struct udevice *dev) { struct ar933x_serial_priv *priv = dev_get_priv(dev); - struct udevice *pinctrl; fdt_addr_t addr; u32 val; - int ret; - - ret = uclass_get_device(UCLASS_PINCTRL, 0, &pinctrl); - if (ret) - return ret; - ret = pinctrl_get_periph_id(pinctrl, dev); - if (ret < 0) - return ret; - ret = pinctrl_request(pinctrl, ret, 0); - if (ret < 0) - return ret; addr = dev_get_addr(dev); if (addr == FDT_ADDR_T_NONE) return -EINVAL; - priv->regs = map_physmem(addr, - AR933X_UART_SIZE, + priv->regs = map_physmem(addr, AR933X_UART_SIZE, MAP_NOCACHE); /* -- cgit