On 04/11/2016 09:57 AM, Wills Wang wrote: > > > On Sunday, April 10, 2016 02:34 AM, Simon Glass wrote: >> Hi Wills, >> >> On 16 March 2016 at 02:59, Wills Wang <[email protected]> wrote: >>> This patch add support for ar933x serial. >>> >>> Reviewed-by: Thomas Chou <[email protected]> >>> Reviewed-by: Daniel Schwierzeck <[email protected]> >>> Reviewed-by: Simon Glass <[email protected]> >>> >>> Signed-off-by: Wills Wang <[email protected]> >> Reviewed-by: Simon Glass <[email protected]> >> >> But please see a comment below. >> >>> --- >>> >>> Changes in v8: >>> - Remove ath79_serial_write/read >>> - Use pinctrl for serial >>> - Add Kconfig dependence for serial option >>> >>> Changes in v7: >>> - remove map_physmem for debug port >>> >>> Changes in v6: >>> - Remove wait loop in putc and getc >>> - Use map_physmem instead of KSEG1ADDR >>> >>> Changes in v5: >>> - remove ar933x_serial_platdata >>> - Import document "qca,ar9330-uart.txt" from kernel >>> - Add support for debug UART >>> >>> Changes in v4: >>> - Auto calculate baudrate for serial driver >>> - Move pinctrl code in serial driver into arch/mips/mach-ath79 >>> - Use get_serial_clock to serial clock source >>> >>> Changes in v3: >>> - Convert serial driver to driver model >>> >>> Changes in v2: >>> - Move serial driver code into drivers/serial >>> >>> .../serial/qca,ar9330-uart.txt | 24 ++ >>> drivers/serial/Kconfig | 18 ++ >>> drivers/serial/Makefile | 1 + >>> drivers/serial/serial_ar933x.c | 255 >>> +++++++++++++++++++++ >>> 4 files changed, 298 insertions(+) >>> create mode 100644 doc/device-tree-bindings/serial/qca,ar9330-uart.txt >>> create mode 100644 drivers/serial/serial_ar933x.c >>> >>> diff --git a/doc/device-tree-bindings/serial/qca,ar9330-uart.txt >>> b/doc/device-tree-bindings/serial/qca,ar9330-uart.txt >>> new file mode 100644 >>> index 0000000..ec576a1 >>> --- /dev/null >>> +++ b/doc/device-tree-bindings/serial/qca,ar9330-uart.txt >>> @@ -0,0 +1,24 @@ >>> +* Qualcomm Atheros AR9330 High-Speed UART >>> + >>> +Required properties: >>> + >>> +- compatible: Must be "qca,ar9330-uart" >>> + >>> +- reg: Specifies the physical base address of the controller and >>> + the length of the memory mapped region. >>> + >>> +Additional requirements: >>> + >>> + Each UART port must have an alias correctly numbered in "aliases" >>> + node. >>> + >>> +Example: >>> + >>> + aliases { >>> + serial0 = &uart0; >>> + }; >>> + >>> + uart0: uart@18020000 { >>> + compatible = "qca,ar9330-uart"; >>> + reg = <0x18020000 0x14>; >>> + }; >>> diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig >>> index 92d4212..d451441 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 >>> @@ -254,6 +263,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 05bdf56..42e493a 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 0000000..d43f9c9 >>> --- /dev/null >>> +++ b/drivers/serial/serial_ar933x.c >>> @@ -0,0 +1,255 @@ >>> +/* >>> + * Copyright (C) 2015-2016 Wills Wang <[email protected]> >>> + * >>> + * SPDX-License-Identifier: GPL-2.0+ >>> + */ >>> + >>> +#include <common.h> >>> +#include <dm.h> >>> +#include <div64.h> >>> +#include <errno.h> >>> +#include <serial.h> >>> +#include <asm/io.h> >>> +#include <asm/addrspace.h> >>> +#include <asm/types.h> >>> +#include <dm/pinctrl.h> >>> +#include <mach/ar71xx_regs.h> >>> + >>> +#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; >> ().Can you check if you need this? It should be called automatically >> by device_probe() which calls pinctrl_select_state(). > Ok, i will remove all explicit pinctrl setting from driver. >>> + >>> + addr = dev_get_addr(dev); >>> + if (addr == FDT_ADDR_T_NONE) >>> + return -EINVAL; >>> + >>> + priv->regs = map_physmem(addr, >>> + AR933X_UART_SIZE, >>> + MAP_NOCACHE); >> can you fill this out to 80cols? > Ok.
Please send subsequent patches on top of mips/next :) http://git.denx.de/?p=u-boot/u-boot-mips.git;a=shortlog;h=refs/heads/next -- Best regards, Marek Vasut _______________________________________________ U-Boot mailing list [email protected] http://lists.denx.de/mailman/listinfo/u-boot

