160b49761SWills Wang /*
260b49761SWills Wang * Copyright (C) 2015-2016 Wills Wang <wills.wang@live.com>
360b49761SWills Wang *
460b49761SWills Wang * SPDX-License-Identifier: GPL-2.0+
560b49761SWills Wang */
660b49761SWills Wang
760b49761SWills Wang #include <common.h>
860b49761SWills Wang #include <dm.h>
960b49761SWills Wang #include <div64.h>
1060b49761SWills Wang #include <errno.h>
1160b49761SWills Wang #include <serial.h>
1260b49761SWills Wang #include <asm/io.h>
1360b49761SWills Wang #include <asm/addrspace.h>
1460b49761SWills Wang #include <asm/types.h>
1560b49761SWills Wang #include <dm/pinctrl.h>
1660b49761SWills Wang #include <mach/ar71xx_regs.h>
1760b49761SWills Wang
1860b49761SWills Wang #define AR933X_UART_DATA_REG 0x00
1960b49761SWills Wang #define AR933X_UART_CS_REG 0x04
2060b49761SWills Wang #define AR933X_UART_CLK_REG 0x08
2160b49761SWills Wang
2260b49761SWills Wang #define AR933X_UART_DATA_TX_RX_MASK 0xff
2360b49761SWills Wang #define AR933X_UART_DATA_RX_CSR BIT(8)
2460b49761SWills Wang #define AR933X_UART_DATA_TX_CSR BIT(9)
2560b49761SWills Wang #define AR933X_UART_CS_IF_MODE_S 2
2660b49761SWills Wang #define AR933X_UART_CS_IF_MODE_M 0x3
2760b49761SWills Wang #define AR933X_UART_CS_IF_MODE_DTE 1
2860b49761SWills Wang #define AR933X_UART_CS_IF_MODE_DCE 2
2960b49761SWills Wang #define AR933X_UART_CS_TX_RDY_ORIDE BIT(7)
3060b49761SWills Wang #define AR933X_UART_CS_RX_RDY_ORIDE BIT(8)
3160b49761SWills Wang #define AR933X_UART_CLK_STEP_M 0xffff
3260b49761SWills Wang #define AR933X_UART_CLK_SCALE_M 0xfff
3360b49761SWills Wang #define AR933X_UART_CLK_SCALE_S 16
3460b49761SWills Wang #define AR933X_UART_CLK_STEP_S 0
3560b49761SWills Wang
3660b49761SWills Wang struct ar933x_serial_priv {
3760b49761SWills Wang void __iomem *regs;
3860b49761SWills Wang };
3960b49761SWills Wang
4060b49761SWills Wang /*
41773f3b25SWills Wang * Baudrate algorithm come from Linux/drivers/tty/serial/ar933x_uart.c
4260b49761SWills Wang * baudrate = (clk / (scale + 1)) * (step * (1 / 2^17))
4360b49761SWills Wang */
ar933x_serial_get_baud(u32 clk,u32 scale,u32 step)4460b49761SWills Wang static u32 ar933x_serial_get_baud(u32 clk, u32 scale, u32 step)
4560b49761SWills Wang {
4660b49761SWills Wang u64 t;
4760b49761SWills Wang u32 div;
4860b49761SWills Wang
4960b49761SWills Wang div = (2 << 16) * (scale + 1);
5060b49761SWills Wang t = clk;
5160b49761SWills Wang t *= step;
5260b49761SWills Wang t += (div / 2);
5360b49761SWills Wang do_div(t, div);
5460b49761SWills Wang
5560b49761SWills Wang return t;
5660b49761SWills Wang }
5760b49761SWills Wang
ar933x_serial_get_scale_step(u32 clk,u32 baud,u32 * scale,u32 * step)5860b49761SWills Wang static void ar933x_serial_get_scale_step(u32 clk, u32 baud,
5960b49761SWills Wang u32 *scale, u32 *step)
6060b49761SWills Wang {
6160b49761SWills Wang u32 tscale, baudrate;
6260b49761SWills Wang long min_diff;
6360b49761SWills Wang
6460b49761SWills Wang *scale = 0;
6560b49761SWills Wang *step = 0;
6660b49761SWills Wang
6760b49761SWills Wang min_diff = baud;
6860b49761SWills Wang for (tscale = 0; tscale < AR933X_UART_CLK_SCALE_M; tscale++) {
6960b49761SWills Wang u64 tstep;
7060b49761SWills Wang int diff;
7160b49761SWills Wang
7260b49761SWills Wang tstep = baud * (tscale + 1);
7360b49761SWills Wang tstep *= (2 << 16);
7460b49761SWills Wang do_div(tstep, clk);
7560b49761SWills Wang
7660b49761SWills Wang if (tstep > AR933X_UART_CLK_STEP_M)
7760b49761SWills Wang break;
7860b49761SWills Wang
7960b49761SWills Wang baudrate = ar933x_serial_get_baud(clk, tscale, tstep);
8060b49761SWills Wang diff = abs(baudrate - baud);
8160b49761SWills Wang if (diff < min_diff) {
8260b49761SWills Wang min_diff = diff;
8360b49761SWills Wang *scale = tscale;
8460b49761SWills Wang *step = tstep;
8560b49761SWills Wang }
8660b49761SWills Wang }
8760b49761SWills Wang }
8860b49761SWills Wang
ar933x_serial_setbrg(struct udevice * dev,int baudrate)8960b49761SWills Wang static int ar933x_serial_setbrg(struct udevice *dev, int baudrate)
9060b49761SWills Wang {
9160b49761SWills Wang struct ar933x_serial_priv *priv = dev_get_priv(dev);
9260b49761SWills Wang u32 val, scale, step;
9360b49761SWills Wang
9460b49761SWills Wang val = get_serial_clock();
9560b49761SWills Wang ar933x_serial_get_scale_step(val, baudrate, &scale, &step);
9660b49761SWills Wang
9760b49761SWills Wang val = (scale & AR933X_UART_CLK_SCALE_M)
9860b49761SWills Wang << AR933X_UART_CLK_SCALE_S;
9960b49761SWills Wang val |= (step & AR933X_UART_CLK_STEP_M)
10060b49761SWills Wang << AR933X_UART_CLK_STEP_S;
10160b49761SWills Wang writel(val, priv->regs + AR933X_UART_CLK_REG);
10260b49761SWills Wang
10360b49761SWills Wang return 0;
10460b49761SWills Wang }
10560b49761SWills Wang
ar933x_serial_putc(struct udevice * dev,const char c)10660b49761SWills Wang static int ar933x_serial_putc(struct udevice *dev, const char c)
10760b49761SWills Wang {
10860b49761SWills Wang struct ar933x_serial_priv *priv = dev_get_priv(dev);
10960b49761SWills Wang u32 data;
11060b49761SWills Wang
11160b49761SWills Wang data = readl(priv->regs + AR933X_UART_DATA_REG);
11260b49761SWills Wang if (!(data & AR933X_UART_DATA_TX_CSR))
11360b49761SWills Wang return -EAGAIN;
11460b49761SWills Wang
11560b49761SWills Wang data = (u32)c | AR933X_UART_DATA_TX_CSR;
11660b49761SWills Wang writel(data, priv->regs + AR933X_UART_DATA_REG);
11760b49761SWills Wang
11860b49761SWills Wang return 0;
11960b49761SWills Wang }
12060b49761SWills Wang
ar933x_serial_getc(struct udevice * dev)12160b49761SWills Wang static int ar933x_serial_getc(struct udevice *dev)
12260b49761SWills Wang {
12360b49761SWills Wang struct ar933x_serial_priv *priv = dev_get_priv(dev);
12460b49761SWills Wang u32 data;
12560b49761SWills Wang
12660b49761SWills Wang data = readl(priv->regs + AR933X_UART_DATA_REG);
12760b49761SWills Wang if (!(data & AR933X_UART_DATA_RX_CSR))
12860b49761SWills Wang return -EAGAIN;
12960b49761SWills Wang
13060b49761SWills Wang writel(AR933X_UART_DATA_RX_CSR, priv->regs + AR933X_UART_DATA_REG);
13160b49761SWills Wang return data & AR933X_UART_DATA_TX_RX_MASK;
13260b49761SWills Wang }
13360b49761SWills Wang
ar933x_serial_pending(struct udevice * dev,bool input)13460b49761SWills Wang static int ar933x_serial_pending(struct udevice *dev, bool input)
13560b49761SWills Wang {
13660b49761SWills Wang struct ar933x_serial_priv *priv = dev_get_priv(dev);
13760b49761SWills Wang u32 data;
13860b49761SWills Wang
13960b49761SWills Wang data = readl(priv->regs + AR933X_UART_DATA_REG);
14060b49761SWills Wang if (input)
14160b49761SWills Wang return (data & AR933X_UART_DATA_RX_CSR) ? 1 : 0;
14260b49761SWills Wang else
14360b49761SWills Wang return (data & AR933X_UART_DATA_TX_CSR) ? 0 : 1;
14460b49761SWills Wang }
14560b49761SWills Wang
ar933x_serial_probe(struct udevice * dev)14660b49761SWills Wang static int ar933x_serial_probe(struct udevice *dev)
14760b49761SWills Wang {
14860b49761SWills Wang struct ar933x_serial_priv *priv = dev_get_priv(dev);
14960b49761SWills Wang fdt_addr_t addr;
15060b49761SWills Wang u32 val;
15160b49761SWills Wang
152*a821c4afSSimon Glass addr = devfdt_get_addr(dev);
15360b49761SWills Wang if (addr == FDT_ADDR_T_NONE)
15460b49761SWills Wang return -EINVAL;
15560b49761SWills Wang
156773f3b25SWills Wang priv->regs = map_physmem(addr, AR933X_UART_SIZE,
15760b49761SWills Wang MAP_NOCACHE);
15860b49761SWills Wang
15960b49761SWills Wang /*
16060b49761SWills Wang * UART controller configuration:
16160b49761SWills Wang * - no DMA
16260b49761SWills Wang * - no interrupt
16360b49761SWills Wang * - DCE mode
16460b49761SWills Wang * - no flow control
16560b49761SWills Wang * - set RX ready oride
16660b49761SWills Wang * - set TX ready oride
16760b49761SWills Wang */
16860b49761SWills Wang val = (AR933X_UART_CS_IF_MODE_DCE << AR933X_UART_CS_IF_MODE_S) |
16960b49761SWills Wang AR933X_UART_CS_TX_RDY_ORIDE | AR933X_UART_CS_RX_RDY_ORIDE;
17060b49761SWills Wang writel(val, priv->regs + AR933X_UART_CS_REG);
17160b49761SWills Wang return 0;
17260b49761SWills Wang }
17360b49761SWills Wang
17460b49761SWills Wang static const struct dm_serial_ops ar933x_serial_ops = {
17560b49761SWills Wang .putc = ar933x_serial_putc,
17660b49761SWills Wang .pending = ar933x_serial_pending,
17760b49761SWills Wang .getc = ar933x_serial_getc,
17860b49761SWills Wang .setbrg = ar933x_serial_setbrg,
17960b49761SWills Wang };
18060b49761SWills Wang
18160b49761SWills Wang static const struct udevice_id ar933x_serial_ids[] = {
18260b49761SWills Wang { .compatible = "qca,ar9330-uart" },
18360b49761SWills Wang { }
18460b49761SWills Wang };
18560b49761SWills Wang
18660b49761SWills Wang U_BOOT_DRIVER(serial_ar933x) = {
18760b49761SWills Wang .name = "serial_ar933x",
18860b49761SWills Wang .id = UCLASS_SERIAL,
18960b49761SWills Wang .of_match = ar933x_serial_ids,
19060b49761SWills Wang .priv_auto_alloc_size = sizeof(struct ar933x_serial_priv),
19160b49761SWills Wang .probe = ar933x_serial_probe,
19260b49761SWills Wang .ops = &ar933x_serial_ops,
19360b49761SWills Wang .flags = DM_FLAG_PRE_RELOC,
19460b49761SWills Wang };
19560b49761SWills Wang
19660b49761SWills Wang #ifdef CONFIG_DEBUG_UART_AR933X
19760b49761SWills Wang
19860b49761SWills Wang #include <debug_uart.h>
19960b49761SWills Wang
_debug_uart_init(void)20060b49761SWills Wang static inline void _debug_uart_init(void)
20160b49761SWills Wang {
20260b49761SWills Wang void __iomem *regs = (void *)CONFIG_DEBUG_UART_BASE;
20360b49761SWills Wang u32 val, scale, step;
20460b49761SWills Wang
20560b49761SWills Wang /*
20660b49761SWills Wang * UART controller configuration:
20760b49761SWills Wang * - no DMA
20860b49761SWills Wang * - no interrupt
20960b49761SWills Wang * - DCE mode
21060b49761SWills Wang * - no flow control
21160b49761SWills Wang * - set RX ready oride
21260b49761SWills Wang * - set TX ready oride
21360b49761SWills Wang */
21460b49761SWills Wang val = (AR933X_UART_CS_IF_MODE_DCE << AR933X_UART_CS_IF_MODE_S) |
21560b49761SWills Wang AR933X_UART_CS_TX_RDY_ORIDE | AR933X_UART_CS_RX_RDY_ORIDE;
21660b49761SWills Wang writel(val, regs + AR933X_UART_CS_REG);
21760b49761SWills Wang
21860b49761SWills Wang ar933x_serial_get_scale_step(CONFIG_DEBUG_UART_CLOCK,
21960b49761SWills Wang CONFIG_BAUDRATE, &scale, &step);
22060b49761SWills Wang
22160b49761SWills Wang val = (scale & AR933X_UART_CLK_SCALE_M)
22260b49761SWills Wang << AR933X_UART_CLK_SCALE_S;
22360b49761SWills Wang val |= (step & AR933X_UART_CLK_STEP_M)
22460b49761SWills Wang << AR933X_UART_CLK_STEP_S;
22560b49761SWills Wang writel(val, regs + AR933X_UART_CLK_REG);
22660b49761SWills Wang }
22760b49761SWills Wang
_debug_uart_putc(int c)22860b49761SWills Wang static inline void _debug_uart_putc(int c)
22960b49761SWills Wang {
23060b49761SWills Wang void __iomem *regs = (void *)CONFIG_DEBUG_UART_BASE;
23160b49761SWills Wang u32 data;
23260b49761SWills Wang
23360b49761SWills Wang do {
23460b49761SWills Wang data = readl(regs + AR933X_UART_DATA_REG);
23560b49761SWills Wang } while (!(data & AR933X_UART_DATA_TX_CSR));
23660b49761SWills Wang
23760b49761SWills Wang data = (u32)c | AR933X_UART_DATA_TX_CSR;
23860b49761SWills Wang writel(data, regs + AR933X_UART_DATA_REG);
23960b49761SWills Wang }
24060b49761SWills Wang
24160b49761SWills Wang DEBUG_UART_FUNCS
24260b49761SWills Wang
24360b49761SWills Wang #endif
244