[U-Boot] [PATCH v3 2/4] mips: ath79: add serial driver for ar933x SOC

Wills Wang wills.wang at live.com
Wed Jan 6 03:58:32 CET 2016



On 01/06/2016 08:25 AM, Simon Glass wrote:
> Hi WIlls,
>
> On 24 December 2015 at 04:22, Wills Wang <wills.wang at live.com> wrote:
>> Signed-off-by: Wills Wang <wills.wang at live.com>
>> ---
>>
>> Changes in v3: None
>> Changes in v2: None
>>
>>   drivers/serial/Makefile        |   1 +
>>   drivers/serial/serial_ar933x.c | 274 +++++++++++++++++++++++++++++++++++++++++
>>   2 files changed, 275 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..6c0d726
>> --- /dev/null
>> +++ b/drivers/serial/serial_ar933x.c
>> @@ -0,0 +1,274 @@
>> +/*
>> + * (C) Copyright 2015
>> + * Wills Wang, <wills.wang at live.com>
>> + *
>> + * SPDX-License-Identifier: GPL-2.0+
>> + */
>> +
>> +#include <common.h>
>> +#include <serial.h>
>> +#include <dm.h>
>> +#include <errno.h>
>> +#include <asm/io.h>
>> +#include <asm/addrspace.h>
>> +#include <asm/types.h>
>> +#include <asm/arch/ar71xx_regs.h>
>> +#include <asm/arch/ar933x_uart.h>
>> +
>> +DECLARE_GLOBAL_DATA_PTR;
>> +
>> +struct ar933x_serial_baudrate{
>> +       u32 baudrate;
>> +       u32 scale;
>> +       u32 step;
>> +};
>> +
>> +const struct ar933x_serial_baudrate baudrate_table_40mhz[] = {
>> +/*  baudrate,   scale,  step */
>> +       {600,       255,    503},
>> +       {1200,      249,    983},
>> +       {2400,      167,    1321},
>> +       {4800,      87,     1384},
>> +       {9600,      45,     1447},
>> +       {14400,     53,     2548},
>> +       {19200,     22,     1447},
>> +       {28800,     26,     2548},
>> +       {38400,     28,     3649},
>> +       {56000,     7,      1468},
>> +       {57600,     34,     6606},
>> +       {115200,    28,     10947},
>> +       {128000,    6,      2936},
>> +       {153600,    18,     9563},
>> +       {230400,    16,     12834},
>> +       {250000,    4,      4096},
>> +       {256000,    6,      5872},
>> +       {460800,    7,      12079},
>> +       {576000,    4,      9437},
>> +       {921600,    3,      12079},
>> +       {1000000,   2,      9830},
>> +       {1152000,   2,      11324},
>> +       {1500000,   0,      4915},
>> +       {2000000,   0,      6553},
>> + };
>> +
>> +const struct ar933x_serial_baudrate baudrate_table_25mhz[] = {
>> +/*  baudrate,   scale,  step */
>> +       {600,       255,    805},
>> +       {1200,      209,    1321},
>> +       {2400,      104,    1321},
>> +       {4800,      54,     1384},
>> +       {9600,      78,     3976},
>> +       {14400,     98,     7474},
>> +       {19200,     55,     5637},
>> +       {28800,     77,     11777},
>> +       {38400,     36,     7449},
>> +       {56000,     4,      1468},
>> +       {57600,     35,     10871},
>> +       {115200,    20,     12683},
>> +       {128000,    11,     8053},
>> +       {153600,    9,      8053},
>> +       {230400,    9,      12079},
>> +       {250000,    6,      9175},
>> +       {256000,    5,      8053},
>> +       {460800,    4,      12079},
>> +       {576000,    3,      12079},
>> +       {921600,    1,      9663},
>> +       {1000000,   1,      10485},
>> +       {1152000,   1,      12079},
>> +       {1500000,   0,      7864},
>> +       {2000000,   0,      10485},
>> +};
>> +
>> +static inline u32 ar933x_read(u32 base, u32 offset)
>> +{
>> +       return readl(KSEG1ADDR(base + offset));
>> +}
>> +
>> +static inline void ar933x_write(u32 base, u32 offset, u32 val)
>> +{
>> +       writel(val, KSEG1ADDR(base + offset));
>> +}
>> +
>> +static int ar933x_serial_init(void)
>> +{
>> +       u32 val;
>> +
>> +       /*
>> +        * Set GPIO10 (UART_SO) as output and enable UART,
>> +        * BIT(15) in GPIO_FUNCTION_1 register must be written with 1
>> +        */
>> +       val = ar933x_read(AR71XX_GPIO_BASE, AR71XX_GPIO_REG_OE);
>> +       val |= BIT(10);
>> +       ar933x_write(AR71XX_GPIO_BASE, AR71XX_GPIO_REG_OE, val);
>> +
>> +       val = ar933x_read(AR71XX_GPIO_BASE, AR71XX_GPIO_REG_FUNC);
>> +       val |= (AR933X_GPIO_FUNC_UART_EN | BIT(15));
>> +       ar933x_write(AR71XX_GPIO_BASE, AR71XX_GPIO_REG_FUNC, val);
>> +
>> +       /*
>> +        * UART controller configuration:
>> +        * - no DMA
>> +        * - no interrupt
>> +        * - DCE mode
>> +        * - no flow control
>> +        * - set RX ready oride
>> +        * - set TX ready oride
>> +        */
>> +       val = AR933X_UART_CS_TX_READY_ORIDE | AR933X_UART_CS_RX_READY_ORIDE
>> +               | (AR933X_UART_CS_IF_MODE_DCE << AR933X_UART_CS_IF_MODE_S);
>> +       ar933x_write(AR933X_UART_BASE, AR933X_UART_CS_REG, val);
>> +       return 0;
>> +}
>> +
>> +#ifdef CONFIG_DM_SERIAL
>> +static int ar933x_serial_setbrg(struct udevice *dev, int baudrate)
>> +{
>> +#else
>> +static void ar933x_serial_setbrg(void)
>> +{
>> +       int baudrate = gd->baudrate;
>> +#endif
>> +       u32 val, scale, step;
>> +       const struct ar933x_serial_baudrate *baudrate_table;
>> +       int i, baudrate_table_size;
>> +
>> +       val = ar933x_read(AR71XX_RESET_BASE, AR933X_RESET_REG_BOOTSTRAP);
>> +       if (val & AR933X_BOOTSTRAP_REF_CLK_40) {
>> +               baudrate_table = baudrate_table_40mhz;
>> +               baudrate_table_size = ARRAY_SIZE(baudrate_table_40mhz);
>> +               scale = (40000000 / (16 * baudrate)) - 1;
>> +               step = 8192;
>> +       } else {
>> +               baudrate_table = baudrate_table_25mhz;
>> +               baudrate_table_size = ARRAY_SIZE(baudrate_table_25mhz);
>> +               scale = (25000000 / (16 * baudrate)) - 1;
>> +               step = 8192;
>> +       }
>> +
>> +       for (i = 0; i < baudrate_table_size; i++) {
>> +               if (baudrate_table[i].baudrate == gd->baudrate) {
>> +                       scale = baudrate_table[i].scale;
>> +                       step = baudrate_table[i].step;
>> +               }
>> +       }
>> +
>> +       val  = ((scale & AR933X_UART_CLOCK_SCALE_M)
>> +                       << AR933X_UART_CLOCK_SCALE_S);
>> +       val |= ((step & AR933X_UART_CLOCK_STEP_M)
>> +                       << AR933X_UART_CLOCK_STEP_S);
>> +       ar933x_write(AR933X_UART_BASE, AR933X_UART_CLOCK_REG, val);
>> +#ifdef CONFIG_DM_SERIAL
>> +       return 0;
>> +#endif
>> +}
>> +
>> +#ifdef CONFIG_DM_SERIAL
>> +static int ar933x_serial_putc(struct udevice *dev, const char c)
>> +#else
>> +static void ar933x_serial_putc(const char c)
>> +#endif
>> +{
>> +       u32 data;
>> +
>> +       if (c == '\n')
>> +#ifdef CONFIG_DM_SERIAL
>> +               ar933x_serial_putc(dev, '\r');
> With driver model the uclass does this for you.
>
>> +#else
>> +               ar933x_serial_putc('\r');
>> +#endif
>> +       do {
>> +               data = ar933x_read(AR933X_UART_BASE, AR933X_UART_DATA_REG);
>> +       } while (!(data & AR933X_UART_DATA_TX_CSR));
> You should not loop here - the uclass does it. Just return -EAGAIN.
>
>> +
>> +       data  = (u32)c | AR933X_UART_DATA_TX_CSR;
>> +       ar933x_write(AR933X_UART_BASE, AR933X_UART_DATA_REG, data);
>> +#ifdef CONFIG_DM_SERIAL
>> +       return 0;
>> +#endif
>> +}
>> +
>> +#ifdef CONFIG_DM_SERIAL
>> +static int ar933x_serial_getc(struct udevice *dev)
>> +#else
>> +static int ar933x_serial_getc(void)
>> +#endif
>> +{
>> +       u32 data;
>> +
>> +       do {
>> +               data = ar933x_read(AR933X_UART_BASE, AR933X_UART_DATA_REG);
>> +       } while (!(data & AR933X_UART_DATA_RX_CSR));
> You should not loop here - the uclass does it. Just return -EAGAIN.
>
>> +
>> +       data = ar933x_read(AR933X_UART_BASE, AR933X_UART_DATA_REG);
>> +       ar933x_write(AR933X_UART_BASE, AR933X_UART_DATA_REG, AR933X_UART_DATA_RX_CSR);
>> +       return data & AR933X_UART_DATA_TX_RX_MASK;
>> +}
>> +
>> +#ifdef CONFIG_DM_SERIAL
>> +static int ar933x_serial_pending(struct udevice *dev, bool input)
>> +{
>> +       u32 data;
>> +
>> +       data = ar933x_read(AR933X_UART_BASE, 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)
>> +{
>> +       ar933x_serial_init();
>> +       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,
>> +       .probe = ar933x_serial_probe,
>> +       .ops    = &ar933x_serial_ops,
>> +       .flags = DM_FLAG_PRE_RELOC,
>> +};
>> +#else
>> +static int ar933x_serial_tstc(void)
>> +{
>> +       u32 data;
>> +
>> +       data = ar933x_read(AR933X_UART_BASE, AR933X_UART_DATA_REG);
>> +       return (data & AR933X_UART_DATA_RX_CSR) ? 1 : 0;
>> +}
>> +
>> +static struct serial_device ar933x_serial_drv = {
>> +       .name   = "ar933x_serial",
>> +       .start  = ar933x_serial_init,
>> +       .stop   = NULL,
>> +       .setbrg = ar933x_serial_setbrg,
>> +       .putc   = ar933x_serial_putc,
>> +       .puts   = default_serial_puts,
>> +       .getc   = ar933x_serial_getc,
>> +       .tstc   = ar933x_serial_tstc,
>> +};
>> +
>> +void ar933x_serial_initialize(void)
>> +{
>> +       serial_register(&ar933x_serial_drv);
>> +}
>> +
>> +__weak struct serial_device *default_serial_console(void)
>> +{
>> +       return &ar933x_serial_drv;
>> +}
>> +#endif
>> --
>> 1.9.1
>>
> Regards,
> SImon
Ok.
I have corrected them in the latest V6 patch.
Please help me to review the V6 patch.

-- 
Best Regards
Wills



More information about the U-Boot mailing list