Am 26.12.2015 um 17:54 schrieb Wills Wang: > > > On 12/26/2015 09:20 PM, Daniel Schwierzeck wrote: >> >> Am 25.12.2015 um 19:56 schrieb Wills Wang: >>> Signed-off-by: Wills Wang <wills.w...@live.com> >>> --- >>> >>> Changes in v4: None >>> Changes in v3: None >>> Changes in v2: None >>> >>> drivers/serial/Makefile | 1 + >>> drivers/serial/serial_ar933x.c | 225 >>> +++++++++++++++++++++++++++++++++++++++++ >>> 2 files changed, 226 insertions(+) >>> create mode 100644 drivers/serial/serial_ar933x.c >>> >>> diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile >>> index dd87147..9a7ad89 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_SERIAL) += 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..efca93c >>> --- /dev/null >>> +++ b/drivers/serial/serial_ar933x.c >>> @@ -0,0 +1,225 @@ >>> +/* >>> + * (C) Copyright 2015 >>> + * Wills Wang, <wills.w...@live.com> >>> + * >>> + * SPDX-License-Identifier: GPL-2.0+ >>> + */ >>> + >>> +#include <common.h> >>> +#include <dm.h> >>> +#include <errno.h> >>> +#include <serial.h> >>> +#include <asm/io.h> >>> +#include <asm/addrspace.h> >>> +#include <asm/div64.h> >> use the existing and generic implementation in include/div64.h > Ok. >>> +#include <asm/types.h> >>> +#include <asm/arch/ar71xx_regs.h> >> #include <mach/ar71xx_regs.h> >> >> I wonder how you can stil compile your code > U-boot create symbolic links from arch/mips/mach-ath79/include/mach > to arch/mips/include/asm/arch.
but it should not. Only if you enable CREATE_ARCH_SYMLINK. Maybe this is some magic for backward compatibility. Anyway the long-term goal is to remove the creation of symbolic links and to use "#include <mach/file.h>". >> >> >>> + >>> +DECLARE_GLOBAL_DATA_PTR; >>> + >>> +#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_platdata { >>> + void __iomem *regs; >>> +}; >> if you always support device-tree, you do not need platform data > Ok. >>> + >>> +struct ar933x_serial_priv { >>> + void __iomem *regs; >>> +}; >>> + >>> +static inline u32 ar933x_serial_read(struct udevice *dev, u32 offset) >>> +{ >>> + struct ar933x_serial_priv *priv = dev_get_priv(dev); >>> + return readl(priv->regs + offset); >>> +} >>> + >>> +static inline void ar933x_serial_write(struct udevice *dev, >>> + u32 val, u32 offset) >>> +{ >>> + struct ar933x_serial_priv *priv = dev_get_priv(dev); >>> + writel(val, priv->regs + offset); >>> +} >>> + >>> +/* >>> + * 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) >>> +{ >>> + 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; >>> + ar933x_serial_write(dev, val, AR933X_UART_CLK_REG); >>> + >>> + return 0; >>> +} >>> + >>> +static int ar933x_serial_putc(struct udevice *dev, const char c) >>> +{ >>> + u32 data; >>> + >>> + if (c == '\n') >>> + ar933x_serial_putc(dev, '\r'); >> remove this, the serial core driver takes care of it > Ok. >>> + >>> + do { >>> + data = ar933x_serial_read(dev, AR933X_UART_DATA_REG); >>> + } while (!(data & AR933X_UART_DATA_TX_CSR)); >> remove this, the serial core driver takes care of it via your pending >> callback (ar933x_serial_pending) > Ok. >>> + >>> + data = (u32)c | AR933X_UART_DATA_TX_CSR; >>> + ar933x_serial_write(dev, data, AR933X_UART_DATA_REG); >>> + >>> + return 0; >>> +} >>> + >>> +static int ar933x_serial_getc(struct udevice *dev) >>> +{ >>> + u32 data; >>> + >>> + do { >>> + data = ar933x_serial_read(dev, AR933X_UART_DATA_REG); >>> + } while (!(data & AR933X_UART_DATA_RX_CSR)); >> dito > Ok. >>> + >>> + data = ar933x_serial_read(dev, AR933X_UART_DATA_REG); >>> + ar933x_serial_write(dev, AR933X_UART_DATA_RX_CSR, >>> + AR933X_UART_DATA_REG); >>> + return data & AR933X_UART_DATA_TX_RX_MASK; >>> +} >>> + >>> +static int ar933x_serial_pending(struct udevice *dev, bool input) >>> +{ >>> + u32 data; >>> + >>> + data = ar933x_serial_read(dev, 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 ar933x_serial_platdata *plat = dev_get_platdata(dev); >>> + u32 val; >>> + >>> + priv->regs = plat->regs; >>> + >>> + /* >>> + * 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; >>> + ar933x_serial_write(dev, val, AR933X_UART_CS_REG); >>> + return 0; >>> +} >>> + >>> +static int ar933x_serial_ofdata_to_platdata(struct udevice *dev) >>> +{ >>> + struct ar933x_serial_platdata *plat = dev_get_platdata(dev); >>> + fdt_addr_t addr; >>> + >>> + addr = dev_get_addr(dev); >>> + if (addr == FDT_ADDR_T_NONE) >>> + return -EINVAL; >>> + >>> + plat->regs = map_physmem(addr, >>> + AR933X_UART_SIZE, >>> + MAP_NOCACHE); >> move this code to function ar933x_serial_probe and drop this function > Ok. >>> + 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 = "ath79,ar933x-uart" }, >>> + { } >>> +}; >>> + >>> +U_BOOT_DRIVER(serial_ar933x) = { >>> + .name = "serial_ar933x", >>> + .id = UCLASS_SERIAL, >>> + .of_match = ar933x_serial_ids, >>> + .ofdata_to_platdata = ar933x_serial_ofdata_to_platdata, >>> + .platdata_auto_alloc_size = sizeof(struct ar933x_serial_platdata), >> drop the two lines, you do not need to allocate platdata >> > Ok. >>> + .priv_auto_alloc_size = sizeof(struct ar933x_serial_priv), >>> + .probe = ar933x_serial_probe, >>> + .ops = &ar933x_serial_ops, >>> + .flags = DM_FLAG_PRE_RELOC, >>> +}; >>> > -- - Daniel _______________________________________________ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot