Re: [U-Boot] [PATCH v4 4/8] mips: ath79: add serial driver for ar933x SOC

2015-12-27 Thread Thomas Chou

Hi Wills,

On 2015年12月27日 14:28, Wills Wang wrote:

+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


+
+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)



Serial core driver don't query and wait the pending function before
"serial_getc" and "serial_putc", so these statements can't remove,
or board don't work.


As I wrote in the v3 patch review, both the getc() and putc() should 
return -EAGAIN if there is no available data to read or not ready to 
write. The polling is done in the serial-uclass.c


Regards,
Thomas
___
U-Boot mailing list
U-Boot@lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot


Re: [U-Boot] [PATCH v4 4/8] mips: ath79: add serial driver for ar933x SOC

2015-12-27 Thread Thomas Chou

Hi Wills,

On 2015年12月26日 21:20, Daniel Schwierzeck wrote:

+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


+   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



It might be another option to keep platdata and ofdata_to_platdata(), 
and remove the priv data. Let ofdata_to_platdata() do the DT conversion 
and probe() detect and initialize the hardware. This is what these func 
expected to do. The priv data is needed only when there is variable data 
to save per device.


Best regards,
Thomas

___
U-Boot mailing list
U-Boot@lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot


Re: [U-Boot] [PATCH v4 4/8] mips: ath79: add serial driver for ar933x SOC

2015-12-27 Thread Thomas Chou

Hi Wills,

Please note the following,

1. add this uart to drivers/serial/Kconfig .

2. add debug uart support. see include/debug_uart.h . also add it to Kconfig

3. cp linux/Documentation/devicetree/bindings/serial/qca,ar9330-uart.txt
  u-boot/doc/device-tree-bindings/serial/

4. to save change to xxx_defconfig, run
   make savedefconfig
   cp defconfig configs/xxx_defconfig

Best regards,
Thomas
___
U-Boot mailing list
U-Boot@lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot


Re: [U-Boot] [PATCH v4 4/8] mips: ath79: add serial driver for ar933x SOC

2015-12-26 Thread 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 
---

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 000..efca93c
--- /dev/null
+++ b/drivers/serial/serial_ar933x.c
@@ -0,0 +1,225 @@
+/*
+ * (C) Copyright 2015
+ * Wills Wang, 
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 

use the existing and generic implementation in include/div64.h

Ok.

+#include 
+#include 

#include 

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.




+
+DECLARE_GLOBAL_DATA_PTR;
+
+#define AR933X_UART_DATA_REG0x00
+#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_S2
+#define AR933X_UART_CS_IF_MODE_M0x3
+#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  0x
+#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, , );
+
+   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 

Re: [U-Boot] [PATCH v4 4/8] mips: ath79: add serial driver for ar933x SOC

2015-12-26 Thread Daniel Schwierzeck


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 
>>> ---
>>>
>>> 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 000..efca93c
>>> --- /dev/null
>>> +++ b/drivers/serial/serial_ar933x.c
>>> @@ -0,0 +1,225 @@
>>> +/*
>>> + * (C) Copyright 2015
>>> + * Wills Wang, 
>>> + *
>>> + * SPDX-License-Identifier: GPL-2.0+
>>> + */
>>> +
>>> +#include 
>>> +#include 
>>> +#include 
>>> +#include 
>>> +#include 
>>> +#include 
>>> +#include 
>> use the existing and generic implementation in include/div64.h
> Ok.
>>> +#include 
>>> +#include 
>> #include 
>>
>> 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 ".

>>
>>
>>> +
>>> +DECLARE_GLOBAL_DATA_PTR;
>>> +
>>> +#define AR933X_UART_DATA_REG0x00
>>> +#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_S2
>>> +#define AR933X_UART_CS_IF_MODE_M0x3
>>> +#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  0x
>>> +#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, , );
>>> +
>>> +val  = (scale & AR933X_UART_CLK_SCALE_M)
>>> +<< 

Re: [U-Boot] [PATCH v4 4/8] mips: ath79: add serial driver for ar933x SOC

2015-12-26 Thread Daniel Schwierzeck


Am 25.12.2015 um 19:56 schrieb Wills Wang:
> Signed-off-by: Wills Wang 
> ---
> 
> 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 000..efca93c
> --- /dev/null
> +++ b/drivers/serial/serial_ar933x.c
> @@ -0,0 +1,225 @@
> +/*
> + * (C) Copyright 2015
> + * Wills Wang, 
> + *
> + * SPDX-License-Identifier: GPL-2.0+
> + */
> +
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 

use the existing and generic implementation in include/div64.h

> +#include 
> +#include 

#include 

I wonder how you can stil compile your code


> +
> +DECLARE_GLOBAL_DATA_PTR;
> +
> +#define AR933X_UART_DATA_REG0x00
> +#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_S2
> +#define AR933X_UART_CS_IF_MODE_M0x3
> +#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  0x
> +#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

> +
> +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, , );
> +
> + 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

> +
> + do {
> + data = ar933x_serial_read(dev, AR933X_UART_DATA_REG);
> + } while (!(data & AR933X_UART_DATA_TX_CSR));

remove this, the serial 

Re: [U-Boot] [PATCH v4 4/8] mips: ath79: add serial driver for ar933x SOC

2015-12-26 Thread 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 
---

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 000..efca93c
--- /dev/null
+++ b/drivers/serial/serial_ar933x.c
@@ -0,0 +1,225 @@
+/*
+ * (C) Copyright 2015
+ * Wills Wang, 
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 

use the existing and generic implementation in include/div64.h


+#include 
+#include 

#include 

I wonder how you can stil compile your code



+
+DECLARE_GLOBAL_DATA_PTR;
+
+#define AR933X_UART_DATA_REG0x00
+#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_S2
+#define AR933X_UART_CS_IF_MODE_M0x3
+#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  0x
+#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


+
+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, , );
+
+   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


+
+   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)



Serial core driver don't query and wait the pending function before

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

2015-12-25 Thread Wills Wang
Signed-off-by: Wills Wang 
---

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 000..efca93c
--- /dev/null
+++ b/drivers/serial/serial_ar933x.c
@@ -0,0 +1,225 @@
+/*
+ * (C) Copyright 2015
+ * Wills Wang, 
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#define AR933X_UART_DATA_REG0x00
+#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_S2
+#define AR933X_UART_CS_IF_MODE_M0x3
+#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  0x
+#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;
+};
+
+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, , );
+
+   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');
+
+   do {
+   data = ar933x_serial_read(dev, AR933X_UART_DATA_REG);
+   } while (!(data & AR933X_UART_DATA_TX_CSR));
+
+   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));
+
+   data = ar933x_serial_read(dev, AR933X_UART_DATA_REG);
+   ar933x_serial_write(dev, AR933X_UART_DATA_RX_CSR,
+   AR933X_UART_DATA_REG);
+   return