[U-Boot] [PATCH 1/2] nios2: remap and translate reg address in device tree

As the io space remapping ioremap() and bridge address translation fdt_translate_address() are not usually used in u-boot driver model by dev_get_addr(). We would better convert the reg address map in the device tree of nios2 boards, so that it is io mapped and bridge translated.
Signed-off-by: Thomas Chou thomas@wytron.com.tw --- arch/nios2/dts/3c120_devboard.dts | 171 +++++++++++++++----------------------- 1 file changed, 69 insertions(+), 102 deletions(-)
diff --git a/arch/nios2/dts/3c120_devboard.dts b/arch/nios2/dts/3c120_devboard.dts index 02524ab..70d71a5 100644 --- a/arch/nios2/dts/3c120_devboard.dts +++ b/arch/nios2/dts/3c120_devboard.dts @@ -14,6 +14,73 @@ #address-cells = <1>; #size-cells = <1>;
+ aliases { + console = &jtag_uart; + }; + + timer_1ms: timer@0x400000 { + compatible = "altr,timer-1.0"; + reg = <0xe8400000 0x00000020>; + interrupt-parent = <&cpu>; + interrupts = <11>; + clock-frequency = <125000000>; + u-boot,dm-pre-reloc; + }; + + jtag_uart: serial@0x4d50 { + compatible = "altr,juart-1.0"; + reg = <0xe8004d50 0x00000008>; + interrupt-parent = <&cpu>; + interrupts = <1>; + u-boot,dm-pre-reloc; + }; + + tse_mac: ethernet@0x4000 { + compatible = "altr,tse-1.0"; + reg = <0xe8004000 0x00000400>, + <0xe8004400 0x00000040>, + <0xe8004800 0x00000040>, + <0xe8002000 0x00002000>; + reg-names = "control_port", "rx_csr", "tx_csr", "s1"; + interrupt-parent = <&cpu>; + interrupts = <2 3>; + interrupt-names = "rx_irq", "tx_irq"; + rx-fifo-depth = <8192>; + tx-fifo-depth = <8192>; + max-frame-size = <1518>; + local-mac-address = [ 00 00 00 00 00 00 ]; + phy-mode = "rgmii-id"; + phy-handle = <&phy0>; + tse_mac_mdio: mdio { + compatible = "altr,tse-mdio"; + #address-cells = <1>; + #size-cells = <0>; + phy0: ethernet-phy@18 { + reg = <18>; + device_type = "ethernet-phy"; + }; + }; + }; + + uart: serial@0x4c80 { + compatible = "altr,uart-1.0"; + reg = <0xe8004c80 0x00000020>; + interrupt-parent = <&cpu>; + interrupts = <10>; + current-speed = <115200>; + clock-frequency = <62500000>; + u-boot,dm-pre-reloc; + }; + + user_led_pio_8out: gpio@0x4cc0 { + compatible = "altr,pio-1.0"; + reg = <0xe8004cc0 0x00000010>; + resetvalue = <255>; + width = <8>; + #gpio-cells = <2>; + gpio-controller; + }; + cpus { #address-cells = <1>; #size-cells = <0>; @@ -46,108 +113,8 @@
memory@0 { device_type = "memory"; - reg = <0x10000000 0x08000000>, - <0x07fff400 0x00000400>; + reg = <0xd0000000 0x08000000>, + <0xc7fff400 0x00000400>; };
- sopc@0 { - device_type = "soc"; - ranges; - #address-cells = <1>; - #size-cells = <1>; - compatible = "altr,avalon", "simple-bus"; - bus-frequency = <125000000>; - - pb_cpu_to_io: bridge@0x8000000 { - compatible = "simple-bus"; - reg = <0x08000000 0x00800000>; - #address-cells = <1>; - #size-cells = <1>; - ranges = <0x00002000 0x08002000 0x00002000>, - <0x00004000 0x08004000 0x00000400>, - <0x00004400 0x08004400 0x00000040>, - <0x00004800 0x08004800 0x00000040>, - <0x00004c80 0x08004c80 0x00000020>, - <0x00004d50 0x08004d50 0x00000008>, - <0x00008000 0x08008000 0x00000020>, - <0x00400000 0x08400000 0x00000020>; - - timer_1ms: timer@0x400000 { - compatible = "altr,timer-1.0"; - reg = <0x00400000 0x00000020>; - interrupt-parent = <&cpu>; - interrupts = <11>; - clock-frequency = <125000000>; - }; - - timer_0: timer@0x8000 { - compatible = "altr,timer-1.0"; - reg = < 0x00008000 0x00000020 >; - interrupt-parent = < &cpu >; - interrupts = < 5 >; - clock-frequency = < 125000000 >; - }; - - jtag_uart: serial@0x4d50 { - compatible = "altr,juart-1.0"; - reg = <0x00004d50 0x00000008>; - interrupt-parent = <&cpu>; - interrupts = <1>; - }; - - tse_mac: ethernet@0x4000 { - compatible = "altr,tse-1.0"; - reg = <0x00004000 0x00000400>, - <0x00004400 0x00000040>, - <0x00004800 0x00000040>, - <0x00002000 0x00002000>; - reg-names = "control_port", "rx_csr", "tx_csr", "s1"; - interrupt-parent = <&cpu>; - interrupts = <2 3>; - interrupt-names = "rx_irq", "tx_irq"; - rx-fifo-depth = <8192>; - tx-fifo-depth = <8192>; - max-frame-size = <1518>; - local-mac-address = [ 00 00 00 00 00 00 ]; - phy-mode = "rgmii-id"; - phy-handle = <&phy0>; - tse_mac_mdio: mdio { - compatible = "altr,tse-mdio"; - #address-cells = <1>; - #size-cells = <0>; - phy0: ethernet-phy@18 { - reg = <18>; - device_type = "ethernet-phy"; - }; - }; - }; - - uart: serial@0x4c80 { - compatible = "altr,uart-1.0"; - reg = <0x00004c80 0x00000020>; - interrupt-parent = <&cpu>; - interrupts = <10>; - current-speed = <115200>; - clock-frequency = <62500000>; - }; - }; - - cfi_flash_64m: flash@0x0 { - compatible = "cfi-flash"; - reg = <0x00000000 0x04000000>; - bank-width = <2>; - device-width = <1>; - #address-cells = <1>; - #size-cells = <1>; - - partition@800000 { - reg = <0x00800000 0x01e00000>; - label = "JFFS2 Filesystem"; - }; - }; - }; - - chosen { - bootargs = "debug console=ttyJ0,115200"; - }; };

Convert altera_jtag_uart to driver model.
Signed-off-by: Thomas Chou thomas@wytron.com.tw --- configs/nios2-generic_defconfig | 3 + drivers/serial/Kconfig | 13 ++++ drivers/serial/altera_jtag_uart.c | 124 +++++++++++++++++++++----------------- include/configs/nios2-generic.h | 3 - 4 files changed, 84 insertions(+), 59 deletions(-)
diff --git a/configs/nios2-generic_defconfig b/configs/nios2-generic_defconfig index 9c1bec5..9dc6a72 100644 --- a/configs/nios2-generic_defconfig +++ b/configs/nios2-generic_defconfig @@ -1,4 +1,5 @@ CONFIG_NIOS2=y +CONFIG_DM_SERIAL=y CONFIG_TARGET_NIOS2_GENERIC=y CONFIG_DEFAULT_DEVICE_TREE="3c120_devboard" CONFIG_HUSH_PARSER=y @@ -14,3 +15,5 @@ CONFIG_CMD_PING=y CONFIG_OF_CONTROL=y CONFIG_NET_RANDOM_ETHADDR=y CONFIG_DM=y +CONFIG_ALTERA_JTAG_UART=y +CONFIG_ALTERA_JTAG_UART_BYPASS=y diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index ccb80d2..5a8cb3a 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig @@ -109,6 +109,19 @@ config DEBUG_UART_SHIFT value. Use this value to specify the shift to use, where 0=byte registers, 2=32-bit word registers, etc.
+config ALTERA_JTAG_UART + bool "Altera JTAG UART support" + depends on NIOS2 && DM_SERIAL + help + Select this to enable an JTAG UART for Altera devices. + +config ALTERA_JTAG_UART_BYPASS + bool "Bypass output when no connection" + depends on ALTERA_JTAG_UART + help + Bypass console output and keep going even if there is no + JTAG terminal connection with the host. + config ROCKCHIP_SERIAL bool "Rockchip on-chip UART support" depends on ARCH_UNIPHIER && DM_SERIAL diff --git a/drivers/serial/altera_jtag_uart.c b/drivers/serial/altera_jtag_uart.c index 9a81402..37a5133 100644 --- a/drivers/serial/altera_jtag_uart.c +++ b/drivers/serial/altera_jtag_uart.c @@ -6,98 +6,110 @@ */
#include <common.h> -#include <watchdog.h> +#include <dm.h> #include <asm/io.h> -#include <linux/compiler.h> #include <serial.h>
-typedef volatile struct { +DECLARE_GLOBAL_DATA_PTR; + +struct altera_jtaguart_regs { unsigned data; /* Data register */ unsigned control; /* Control register */ -} nios_jtag_t; +}; + +struct altera_jtaguart_platdata { + struct altera_jtaguart_regs *reg; +};
/* data register */ #define NIOS_JTAG_RVALID (1<<15) /* Read valid */ -#define NIOS_JTAG_DATA(d) ((d)&0x0ff) /* Read data */ -#define NIOS_JTAG_RAVAIL(d) ((d)>>16) /* Read space avail */
/* control register */ -#define NIOS_JTAG_RE (1 << 0) /* read intr enable */ -#define NIOS_JTAG_WE (1 << 1) /* write intr enable */ -#define NIOS_JTAG_RI (1 << 8) /* read intr pending */ -#define NIOS_JTAG_WI (1 << 9) /* write intr pending*/ #define NIOS_JTAG_AC (1 << 10) /* activity indicator */ #define NIOS_JTAG_RRDY (1 << 12) /* read available */ #define NIOS_JTAG_WSPACE(d) ((d)>>16) /* Write space avail */
-DECLARE_GLOBAL_DATA_PTR; - -/*------------------------------------------------------------------ - * JTAG acts as the serial port - *-----------------------------------------------------------------*/ -static nios_jtag_t *jtag = (nios_jtag_t *)CONFIG_SYS_NIOS_CONSOLE; - -static void altera_jtag_serial_setbrg(void) -{ -} - -static int altera_jtag_serial_init(void) +static int altera_jtaguart_putc(struct udevice *dev, const char c) { - return 0; -} + struct altera_jtaguart_platdata *plat = dev->platdata; + struct altera_jtaguart_regs *const regs = plat->reg;
-static void altera_jtag_serial_putc(char c) -{ while (1) { - unsigned st = readl(&jtag->control); + unsigned st = readl(®s->control); if (NIOS_JTAG_WSPACE(st)) break; #ifdef CONFIG_ALTERA_JTAG_UART_BYPASS if (!(st & NIOS_JTAG_AC)) /* no connection */ - return; + return 0; #endif - WATCHDOG_RESET(); } - writel ((unsigned char)c, &jtag->data); + writel((unsigned char)c, ®s->data); + + return 0; }
-static int altera_jtag_serial_tstc(void) +static int altera_jtaguart_pending(struct udevice *dev, bool input) { - return ( readl (&jtag->control) & NIOS_JTAG_RRDY); + struct altera_jtaguart_platdata *plat = dev->platdata; + struct altera_jtaguart_regs *const regs = plat->reg; + unsigned st = readl(®s->control); + + if (input) + return (st & NIOS_JTAG_RRDY) ? 1 : 0; + else + return NIOS_JTAG_WSPACE(st) ? 0 : 1; }
-static int altera_jtag_serial_getc(void) +static int altera_jtaguart_getc(struct udevice *dev) { - int c; + struct altera_jtaguart_platdata *plat = dev->platdata; + struct altera_jtaguart_regs *const regs = plat->reg; unsigned val;
- while (1) { - WATCHDOG_RESET (); - val = readl (&jtag->data); - if (val & NIOS_JTAG_RVALID) - break; - } - c = val & 0x0ff; - return (c); + while (!((val = readl(®s->data)) & NIOS_JTAG_RVALID)) + ; + + return (val & 0xff); }
-static struct serial_device altera_jtag_serial_drv = { - .name = "altera_jtag_uart", - .start = altera_jtag_serial_init, - .stop = NULL, - .setbrg = altera_jtag_serial_setbrg, - .putc = altera_jtag_serial_putc, - .puts = default_serial_puts, - .getc = altera_jtag_serial_getc, - .tstc = altera_jtag_serial_tstc, -}; +static int altera_jtaguart_setbrg(struct udevice *dev, int baudrate) +{ + return 0; +}
-void altera_jtag_serial_initialize(void) +static int altera_jtaguart_probe(struct udevice *dev) { - serial_register(&altera_jtag_serial_drv); + return 0; }
-__weak struct serial_device *default_serial_console(void) +static int altera_jtaguart_ofdata_to_platdata(struct udevice *dev) { - return &altera_jtag_serial_drv; + struct altera_jtaguart_platdata *plat = dev_get_platdata(dev); + + plat->reg = (void *)dev_get_addr(dev); + + return 0; } + +static const struct dm_serial_ops altera_jtaguart_ops = { + .putc = altera_jtaguart_putc, + .pending = altera_jtaguart_pending, + .getc = altera_jtaguart_getc, + .setbrg = altera_jtaguart_setbrg, +}; + +static const struct udevice_id altera_jtaguart_ids[] = { + { .compatible = "altr,juart-1.0", }, + { } +}; + +U_BOOT_DRIVER(altera_jtaguart) = { + .name = "altera_jtaguart", + .id = UCLASS_SERIAL, + .of_match = altera_jtaguart_ids, + .ofdata_to_platdata = altera_jtaguart_ofdata_to_platdata, + .platdata_auto_alloc_size = sizeof(struct altera_jtaguart_platdata), + .probe = altera_jtaguart_probe, + .ops = &altera_jtaguart_ops, + .flags = DM_FLAG_PRE_RELOC, +}; diff --git a/include/configs/nios2-generic.h b/include/configs/nios2-generic.h index 66ad2f0..bd6d45c 100644 --- a/include/configs/nios2-generic.h +++ b/include/configs/nios2-generic.h @@ -23,14 +23,11 @@ /* * SERIAL */ -#define CONFIG_ALTERA_JTAG_UART #if defined(CONFIG_ALTERA_JTAG_UART) -# define CONFIG_SYS_NIOS_CONSOLE CONFIG_SYS_JTAG_UART_BASE #else # define CONFIG_SYS_NIOS_CONSOLE CONFIG_SYS_UART_BASE #endif
-#define CONFIG_ALTERA_JTAG_UART_BYPASS #define CONFIG_SYS_NIOS_FIXEDBAUD #define CONFIG_BAUDRATE CONFIG_SYS_UART_BAUD #define CONFIG_SYS_BAUDRATE_TABLE {CONFIG_BAUDRATE}

On Sunday, September 13, 2015 at 10:32:10 AM, Thomas Chou wrote:
Convert altera_jtag_uart to driver model.
Signed-off-by: Thomas Chou thomas@wytron.com.tw
[...]
-static int altera_jtag_serial_init(void) +static int altera_jtaguart_putc(struct udevice *dev, const char c) {
- return 0;
-}
- struct altera_jtaguart_platdata *plat = dev->platdata;
- struct altera_jtaguart_regs *const regs = plat->reg;
-static void altera_jtag_serial_putc(char c) -{ while (1) {
unsigned st = readl(&jtag->control);
if (NIOS_JTAG_WSPACE(st)) break;unsigned st = readl(®s->control);
#ifdef CONFIG_ALTERA_JTAG_UART_BYPASS if (!(st & NIOS_JTAG_AC)) /* no connection */
return;
return 0;
#endif
WATCHDOG_RESET();
Please keep those WATCHDOG_RESET() calls, they're needed in case you do have a WDT on your board.
}
- writel ((unsigned char)c, &jtag->data);
- writel((unsigned char)c, ®s->data);
- return 0;
}
[...]
-static int altera_jtag_serial_getc(void) +static int altera_jtaguart_getc(struct udevice *dev) {
- int c;
- struct altera_jtaguart_platdata *plat = dev->platdata;
- struct altera_jtaguart_regs *const regs = plat->reg; unsigned val;
- while (1) {
WATCHDOG_RESET ();
val = readl (&jtag->data);
if (val & NIOS_JTAG_RVALID)
break;
- }
- c = val & 0x0ff;
- return (c);
- while (!((val = readl(®s->data)) & NIOS_JTAG_RVALID))
Ewww, this is ugly. Please expand it into something like the following, for the sake of readability.
while (1) { val = readl() if (val & cond) break; }
;
- return (val & 0xff);
}
Looks good otherwise, thanks ! :)
[...]

On Sunday, September 13, 2015 at 10:32:09 AM, Thomas Chou wrote:
As the io space remapping ioremap() and bridge address translation fdt_translate_address() are not usually used in u-boot driver model by dev_get_addr(). We would better convert the reg address map in the device tree of nios2 boards, so that it is io mapped and bridge translated.
Signed-off-by: Thomas Chou thomas@wytron.com.tw
I'm not opposed.
btw. It might be just about time to split the DT bits into nios2.dtsi and nios2_3c120_devboard.dts , where the former would contain the generic bits of the binding and the later would only fill in the necessary address ranges and such. I do understand though, that the problem here might be that the hardware is just too flexible.
Best regards, Marek Vasut

+Stefan
Hi,
On 13 September 2015 at 07:39, Marek Vasut marex@denx.de wrote:
On Sunday, September 13, 2015 at 10:32:09 AM, Thomas Chou wrote:
As the io space remapping ioremap() and bridge address translation fdt_translate_address() are not usually used in u-boot driver model by dev_get_addr(). We would better convert the reg address map in the device tree of nios2 boards, so that it is io mapped and bridge translated.
Signed-off-by: Thomas Chou thomas@wytron.com.tw
I'm not opposed.
btw. It might be just about time to split the DT bits into nios2.dtsi and nios2_3c120_devboard.dts , where the former would contain the generic bits of the binding and the later would only fill in the necessary address ranges and such. I do understand though, that the problem here might be that the hardware is just too flexible.
Please do check the patch under discussion here:
http://patchwork.ozlabs.org/patch/513313/
Does it solve your problem?
Regards, Simon

Hi Marek,
On 09/13/2015 09:39 PM, Marek Vasut wrote:
btw. It might be just about time to split the DT bits into nios2.dtsi and nios2_3c120_devboard.dts , where the former would contain the generic bits of the binding and the later would only fill in the necessary address ranges and such. I do understand though, that the problem here might be that the hardware is just too flexible.
Yes, the FPGA hardware is too flexible so that I cannot find a generic part of dts to split into a dtsi. Almost every parameter is programmable. :)
Best regards, Thomas Chou

Update the dts and convert altera_jtag_uart to driver model.
v2 add ioremap. make the change to dts compatible with linux.
Thomas Chou (3): nios2: map physical address to uncached virtual address nios2: remove bridges in device tree nios2: convert altera_jtag_uart to driver model
arch/nios2/cpu/interrupts.c | 4 +- arch/nios2/dts/3c120_devboard.dts | 162 ++++++++++++++++++-------------------- arch/nios2/include/asm/io.h | 5 ++ configs/nios2-generic_defconfig | 3 + drivers/serial/Kconfig | 13 +++ drivers/serial/altera_jtag_uart.c | 125 ++++++++++++++++------------- include/configs/nios2-generic.h | 3 - 7 files changed, 168 insertions(+), 147 deletions(-)

Add ioremap() to map physical address to uncached virtual address. We need this to convert the reg address from the device tree.
The order of headers inclusion in interrupts.c is changed because common.h will include board header that contains IO_REGION_BASE.
In the future, the IO_REGION_BASE should be decided from the device tree.
Signed-off-by: Thomas Chou thomas@wytron.com.tw --- arch/nios2/cpu/interrupts.c | 4 ++-- arch/nios2/include/asm/io.h | 5 +++++ 2 files changed, 7 insertions(+), 2 deletions(-)
diff --git a/arch/nios2/cpu/interrupts.c b/arch/nios2/cpu/interrupts.c index 9d85eb0..1599674 100644 --- a/arch/nios2/cpu/interrupts.c +++ b/arch/nios2/cpu/interrupts.c @@ -8,12 +8,12 @@ * SPDX-License-Identifier: GPL-2.0+ */
+#include <common.h> +#include <command.h> #include <asm/nios2.h> #include <asm/types.h> #include <asm/io.h> #include <asm/ptrace.h> -#include <common.h> -#include <command.h>
/*************************************************************************/ struct irq_action { diff --git a/arch/nios2/include/asm/io.h b/arch/nios2/include/asm/io.h index 69ab23e..b4bd20f 100644 --- a/arch/nios2/include/asm/io.h +++ b/arch/nios2/include/asm/io.h @@ -42,6 +42,11 @@ static inline phys_addr_t virt_to_phys(void * vaddr) return (phys_addr_t)(vaddr); }
+static inline void *ioremap(unsigned long physaddr, unsigned long size) +{ + return (void *)(IO_REGION_BASE | physaddr); +} + extern unsigned char inb (unsigned char *port); extern unsigned short inw (unsigned short *port); extern unsigned inl (unsigned port);

On Sunday, September 13, 2015 at 03:40:04 PM, Thomas Chou wrote:
Add ioremap() to map physical address to uncached virtual address. We need this to convert the reg address from the device tree.
The order of headers inclusion in interrupts.c is changed because common.h will include board header that contains IO_REGION_BASE.
In the future, the IO_REGION_BASE should be decided from the device tree.
Signed-off-by: Thomas Chou thomas@wytron.com.tw
This is good :)
Acked-by: Marek Vasut marex@denx.de
Best regards, Marek Vasut

Hi,
On Sunday, 13 September 2015, Marek Vasut marex@denx.de wrote:
On Sunday, September 13, 2015 at 03:40:04 PM, Thomas Chou wrote:
Add ioremap() to map physical address to uncached virtual address. We need this to convert the reg address from the device tree.
The order of headers inclusion in interrupts.c is changed because common.h will include board header that contains IO_REGION_BASE.
In the future, the IO_REGION_BASE should be decided from the device tree.
Signed-off-by: Thomas Chou thomas@wytron.com.tw
This is good :)
Acked-by: Marek Vasut marex@denx.de
Can we not rely on the 'ranges' property to sort this out?
Regards, Simon

Hi Simon,
On 10/02/2015 06:49 AM, Simon Glass wrote:
Add ioremap() to map physical address to uncached virtual address. We need this to convert the reg address from the device tree.
Can we not rely on the 'ranges' property to sort this out?
The ranges translate address across buses/bridges. The address is still physical address. In the case of nios2, the virtual address map of mmu or nonmmu are different, though the physical address should be the same. So we really need sort of ioremap(). You may find a lots of call to ioremap() in linux drivers. It is quite standard. We also want to use the same dts/dtb for both u-boot and linux. I would suggest ioremap() is the way.
Thanks a lot for your review.
Best regards, Thomas

On 1 October 2015 at 18:16, Thomas Chou thomas@wytron.com.tw wrote:
Hi Simon,
On 10/02/2015 06:49 AM, Simon Glass wrote:
Add ioremap() to map physical address to uncached virtual address. We need this to convert the reg address from the device tree.
Can we not rely on the 'ranges' property to sort this out?
The ranges translate address across buses/bridges. The address is still physical address. In the case of nios2, the virtual address map of mmu or nonmmu are different, though the physical address should be the same. So we really need sort of ioremap(). You may find a lots of call to ioremap() in linux drivers. It is quite standard. We also want to use the same dts/dtb for both u-boot and linux. I would suggest ioremap() is the way.
Yes I see this on another thread. Thanks for explaining it.
Reviewed-by: Simon Glass sjg@chromium.org

As the device tree handlers in driver model does not translate address across bridges, we would remove the bridges in device tree and translate the reg address.
We want to use the same device tree for both u-boot and linux. The ioremap() should be used to map the address returned from dev_get_addr().
Signed-off-by: Thomas Chou thomas@wytron.com.tw --- arch/nios2/dts/3c120_devboard.dts | 157 +++++++++++++++++--------------------- 1 file changed, 71 insertions(+), 86 deletions(-)
diff --git a/arch/nios2/dts/3c120_devboard.dts b/arch/nios2/dts/3c120_devboard.dts index 02524ab..bd32842 100644 --- a/arch/nios2/dts/3c120_devboard.dts +++ b/arch/nios2/dts/3c120_devboard.dts @@ -50,100 +50,85 @@ <0x07fff400 0x00000400>; };
- sopc@0 { - device_type = "soc"; - ranges; - #address-cells = <1>; - #size-cells = <1>; - compatible = "altr,avalon", "simple-bus"; - bus-frequency = <125000000>; - - pb_cpu_to_io: bridge@0x8000000 { - compatible = "simple-bus"; - reg = <0x08000000 0x00800000>; - #address-cells = <1>; - #size-cells = <1>; - ranges = <0x00002000 0x08002000 0x00002000>, - <0x00004000 0x08004000 0x00000400>, - <0x00004400 0x08004400 0x00000040>, - <0x00004800 0x08004800 0x00000040>, - <0x00004c80 0x08004c80 0x00000020>, - <0x00004d50 0x08004d50 0x00000008>, - <0x00008000 0x08008000 0x00000020>, - <0x00400000 0x08400000 0x00000020>; + timer_1ms: timer@0x400000 { + compatible = "altr,timer-1.0"; + reg = <0x08400000 0x00000020>; + interrupt-parent = <&cpu>; + interrupts = <11>; + clock-frequency = <125000000>; + };
- timer_1ms: timer@0x400000 { - compatible = "altr,timer-1.0"; - reg = <0x00400000 0x00000020>; - interrupt-parent = <&cpu>; - interrupts = <11>; - clock-frequency = <125000000>; - }; + timer_0: timer@0x8000 { + compatible = "altr,timer-1.0"; + reg = < 0x08008000 0x00000020 >; + interrupt-parent = < &cpu >; + interrupts = < 5 >; + clock-frequency = < 125000000 >; + };
- timer_0: timer@0x8000 { - compatible = "altr,timer-1.0"; - reg = < 0x00008000 0x00000020 >; - interrupt-parent = < &cpu >; - interrupts = < 5 >; - clock-frequency = < 125000000 >; - }; + jtag_uart: serial@0x4d50 { + compatible = "altr,juart-1.0"; + reg = <0x08004d50 0x00000008>; + interrupt-parent = <&cpu>; + interrupts = <1>; + };
- jtag_uart: serial@0x4d50 { - compatible = "altr,juart-1.0"; - reg = <0x00004d50 0x00000008>; - interrupt-parent = <&cpu>; - interrupts = <1>; + tse_mac: ethernet@0x4000 { + compatible = "altr,tse-1.0"; + reg = <0x08004000 0x00000400>, + <0x08004400 0x00000040>, + <0x08004800 0x00000040>, + <0x08002000 0x00002000>; + reg-names = "control_port", "rx_csr", "tx_csr", "s1"; + interrupt-parent = <&cpu>; + interrupts = <2 3>; + interrupt-names = "rx_irq", "tx_irq"; + rx-fifo-depth = <8192>; + tx-fifo-depth = <8192>; + max-frame-size = <1518>; + local-mac-address = [ 00 00 00 00 00 00 ]; + phy-mode = "rgmii-id"; + phy-handle = <&phy0>; + tse_mac_mdio: mdio { + compatible = "altr,tse-mdio"; + #address-cells = <1>; + #size-cells = <0>; + phy0: ethernet-phy@18 { + reg = <18>; + device_type = "ethernet-phy"; }; + }; + };
- tse_mac: ethernet@0x4000 { - compatible = "altr,tse-1.0"; - reg = <0x00004000 0x00000400>, - <0x00004400 0x00000040>, - <0x00004800 0x00000040>, - <0x00002000 0x00002000>; - reg-names = "control_port", "rx_csr", "tx_csr", "s1"; - interrupt-parent = <&cpu>; - interrupts = <2 3>; - interrupt-names = "rx_irq", "tx_irq"; - rx-fifo-depth = <8192>; - tx-fifo-depth = <8192>; - max-frame-size = <1518>; - local-mac-address = [ 00 00 00 00 00 00 ]; - phy-mode = "rgmii-id"; - phy-handle = <&phy0>; - tse_mac_mdio: mdio { - compatible = "altr,tse-mdio"; - #address-cells = <1>; - #size-cells = <0>; - phy0: ethernet-phy@18 { - reg = <18>; - device_type = "ethernet-phy"; - }; - }; - }; + uart: serial@0x4c80 { + compatible = "altr,uart-1.0"; + reg = <0x08004c80 0x00000020>; + interrupt-parent = <&cpu>; + interrupts = <10>; + current-speed = <115200>; + clock-frequency = <62500000>; + };
- uart: serial@0x4c80 { - compatible = "altr,uart-1.0"; - reg = <0x00004c80 0x00000020>; - interrupt-parent = <&cpu>; - interrupts = <10>; - current-speed = <115200>; - clock-frequency = <62500000>; - }; - }; + user_led_pio_8out: gpio@0x4cc0 { + compatible = "altr,pio-1.0"; + reg = <0x08004cc0 0x00000010>; + resetvalue = <255>; + width = <8>; + #gpio-cells = <2>; + gpio-controller; + };
- cfi_flash_64m: flash@0x0 { - compatible = "cfi-flash"; - reg = <0x00000000 0x04000000>; - bank-width = <2>; - device-width = <1>; - #address-cells = <1>; - #size-cells = <1>; + cfi_flash_64m: flash@0x0 { + compatible = "cfi-flash"; + reg = <0x00000000 0x04000000>; + bank-width = <2>; + device-width = <1>; + #address-cells = <1>; + #size-cells = <1>;
- partition@800000 { - reg = <0x00800000 0x01e00000>; - label = "JFFS2 Filesystem"; - }; + partition@800000 { + reg = <0x00800000 0x01e00000>; + label = "JFFS2 Filesystem"; }; };

Convert altera_jtag_uart to driver model.
Signed-off-by: Thomas Chou thomas@wytron.com.tw --- arch/nios2/dts/3c120_devboard.dts | 5 ++ configs/nios2-generic_defconfig | 3 + drivers/serial/Kconfig | 13 ++++ drivers/serial/altera_jtag_uart.c | 125 +++++++++++++++++++++----------------- include/configs/nios2-generic.h | 3 - 5 files changed, 90 insertions(+), 59 deletions(-)
diff --git a/arch/nios2/dts/3c120_devboard.dts b/arch/nios2/dts/3c120_devboard.dts index bd32842..dfe1ec4 100644 --- a/arch/nios2/dts/3c120_devboard.dts +++ b/arch/nios2/dts/3c120_devboard.dts @@ -71,6 +71,7 @@ reg = <0x08004d50 0x00000008>; interrupt-parent = <&cpu>; interrupts = <1>; + u-boot,dm-pre-reloc; };
tse_mac: ethernet@0x4000 { @@ -132,6 +133,10 @@ }; };
+ aliases { + console = &jtag_uart; + }; + chosen { bootargs = "debug console=ttyJ0,115200"; }; diff --git a/configs/nios2-generic_defconfig b/configs/nios2-generic_defconfig index 9c1bec5..9dc6a72 100644 --- a/configs/nios2-generic_defconfig +++ b/configs/nios2-generic_defconfig @@ -1,4 +1,5 @@ CONFIG_NIOS2=y +CONFIG_DM_SERIAL=y CONFIG_TARGET_NIOS2_GENERIC=y CONFIG_DEFAULT_DEVICE_TREE="3c120_devboard" CONFIG_HUSH_PARSER=y @@ -14,3 +15,5 @@ CONFIG_CMD_PING=y CONFIG_OF_CONTROL=y CONFIG_NET_RANDOM_ETHADDR=y CONFIG_DM=y +CONFIG_ALTERA_JTAG_UART=y +CONFIG_ALTERA_JTAG_UART_BYPASS=y diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index ccb80d2..5a8cb3a 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig @@ -109,6 +109,19 @@ config DEBUG_UART_SHIFT value. Use this value to specify the shift to use, where 0=byte registers, 2=32-bit word registers, etc.
+config ALTERA_JTAG_UART + bool "Altera JTAG UART support" + depends on NIOS2 && DM_SERIAL + help + Select this to enable an JTAG UART for Altera devices. + +config ALTERA_JTAG_UART_BYPASS + bool "Bypass output when no connection" + depends on ALTERA_JTAG_UART + help + Bypass console output and keep going even if there is no + JTAG terminal connection with the host. + config ROCKCHIP_SERIAL bool "Rockchip on-chip UART support" depends on ARCH_UNIPHIER && DM_SERIAL diff --git a/drivers/serial/altera_jtag_uart.c b/drivers/serial/altera_jtag_uart.c index 9a81402..74a199d 100644 --- a/drivers/serial/altera_jtag_uart.c +++ b/drivers/serial/altera_jtag_uart.c @@ -6,98 +6,111 @@ */
#include <common.h> -#include <watchdog.h> +#include <dm.h> #include <asm/io.h> -#include <linux/compiler.h> #include <serial.h>
-typedef volatile struct { +DECLARE_GLOBAL_DATA_PTR; + +struct altera_jtaguart_regs { unsigned data; /* Data register */ unsigned control; /* Control register */ -} nios_jtag_t; +}; + +struct altera_jtaguart_platdata { + struct altera_jtaguart_regs *reg; +};
/* data register */ #define NIOS_JTAG_RVALID (1<<15) /* Read valid */ -#define NIOS_JTAG_DATA(d) ((d)&0x0ff) /* Read data */ -#define NIOS_JTAG_RAVAIL(d) ((d)>>16) /* Read space avail */
/* control register */ -#define NIOS_JTAG_RE (1 << 0) /* read intr enable */ -#define NIOS_JTAG_WE (1 << 1) /* write intr enable */ -#define NIOS_JTAG_RI (1 << 8) /* read intr pending */ -#define NIOS_JTAG_WI (1 << 9) /* write intr pending*/ #define NIOS_JTAG_AC (1 << 10) /* activity indicator */ #define NIOS_JTAG_RRDY (1 << 12) /* read available */ #define NIOS_JTAG_WSPACE(d) ((d)>>16) /* Write space avail */
-DECLARE_GLOBAL_DATA_PTR; - -/*------------------------------------------------------------------ - * JTAG acts as the serial port - *-----------------------------------------------------------------*/ -static nios_jtag_t *jtag = (nios_jtag_t *)CONFIG_SYS_NIOS_CONSOLE; - -static void altera_jtag_serial_setbrg(void) -{ -} - -static int altera_jtag_serial_init(void) +static int altera_jtaguart_putc(struct udevice *dev, const char c) { - return 0; -} + struct altera_jtaguart_platdata *plat = dev->platdata; + struct altera_jtaguart_regs *const regs = plat->reg;
-static void altera_jtag_serial_putc(char c) -{ while (1) { - unsigned st = readl(&jtag->control); + unsigned st = readl(®s->control); if (NIOS_JTAG_WSPACE(st)) break; #ifdef CONFIG_ALTERA_JTAG_UART_BYPASS if (!(st & NIOS_JTAG_AC)) /* no connection */ - return; + return 0; #endif - WATCHDOG_RESET(); } - writel ((unsigned char)c, &jtag->data); + writel((unsigned char)c, ®s->data); + + return 0; }
-static int altera_jtag_serial_tstc(void) +static int altera_jtaguart_pending(struct udevice *dev, bool input) { - return ( readl (&jtag->control) & NIOS_JTAG_RRDY); + struct altera_jtaguart_platdata *plat = dev->platdata; + struct altera_jtaguart_regs *const regs = plat->reg; + unsigned st = readl(®s->control); + + if (input) + return (st & NIOS_JTAG_RRDY) ? 1 : 0; + else + return NIOS_JTAG_WSPACE(st) ? 0 : 1; }
-static int altera_jtag_serial_getc(void) +static int altera_jtaguart_getc(struct udevice *dev) { - int c; + struct altera_jtaguart_platdata *plat = dev->platdata; + struct altera_jtaguart_regs *const regs = plat->reg; unsigned val;
- while (1) { - WATCHDOG_RESET (); - val = readl (&jtag->data); - if (val & NIOS_JTAG_RVALID) - break; - } - c = val & 0x0ff; - return (c); + while (!((val = readl(®s->data)) & NIOS_JTAG_RVALID)) + ; + + return (val & 0xff); }
-static struct serial_device altera_jtag_serial_drv = { - .name = "altera_jtag_uart", - .start = altera_jtag_serial_init, - .stop = NULL, - .setbrg = altera_jtag_serial_setbrg, - .putc = altera_jtag_serial_putc, - .puts = default_serial_puts, - .getc = altera_jtag_serial_getc, - .tstc = altera_jtag_serial_tstc, -}; +static int altera_jtaguart_setbrg(struct udevice *dev, int baudrate) +{ + return 0; +}
-void altera_jtag_serial_initialize(void) +static int altera_jtaguart_probe(struct udevice *dev) { - serial_register(&altera_jtag_serial_drv); + return 0; }
-__weak struct serial_device *default_serial_console(void) +static int altera_jtaguart_ofdata_to_platdata(struct udevice *dev) { - return &altera_jtag_serial_drv; + struct altera_jtaguart_platdata *plat = dev_get_platdata(dev); + + plat->reg = ioremap(dev_get_addr(dev), + sizeof(struct altera_jtaguart_regs)); + + return 0; } + +static const struct dm_serial_ops altera_jtaguart_ops = { + .putc = altera_jtaguart_putc, + .pending = altera_jtaguart_pending, + .getc = altera_jtaguart_getc, + .setbrg = altera_jtaguart_setbrg, +}; + +static const struct udevice_id altera_jtaguart_ids[] = { + { .compatible = "altr,juart-1.0", }, + { } +}; + +U_BOOT_DRIVER(altera_jtaguart) = { + .name = "altera_jtaguart", + .id = UCLASS_SERIAL, + .of_match = altera_jtaguart_ids, + .ofdata_to_platdata = altera_jtaguart_ofdata_to_platdata, + .platdata_auto_alloc_size = sizeof(struct altera_jtaguart_platdata), + .probe = altera_jtaguart_probe, + .ops = &altera_jtaguart_ops, + .flags = DM_FLAG_PRE_RELOC, +}; diff --git a/include/configs/nios2-generic.h b/include/configs/nios2-generic.h index 66ad2f0..bd6d45c 100644 --- a/include/configs/nios2-generic.h +++ b/include/configs/nios2-generic.h @@ -23,14 +23,11 @@ /* * SERIAL */ -#define CONFIG_ALTERA_JTAG_UART #if defined(CONFIG_ALTERA_JTAG_UART) -# define CONFIG_SYS_NIOS_CONSOLE CONFIG_SYS_JTAG_UART_BASE #else # define CONFIG_SYS_NIOS_CONSOLE CONFIG_SYS_UART_BASE #endif
-#define CONFIG_ALTERA_JTAG_UART_BYPASS #define CONFIG_SYS_NIOS_FIXEDBAUD #define CONFIG_BAUDRATE CONFIG_SYS_UART_BAUD #define CONFIG_SYS_BAUDRATE_TABLE {CONFIG_BAUDRATE}

Hi Thomas,
added Simon and Stephen to cc on this.
On 13.09.2015 10:32, Thomas Chou wrote:
As the io space remapping ioremap() and bridge address translation fdt_translate_address() are not usually used in u-boot driver model by dev_get_addr(). We would better convert the reg address map in the device tree of nios2 boards, so that it is io mapped and bridge translated.
So you are changing the DT sources for your platform because the U-Boot implementation does support the bus translation correctly (ranges properties)? I think this is the wrong approach. We need to make sure that U-Boot supports DT correctly instead. I have a patch queued to enable this. Please take a look at this thread:
https://patchwork.ozlabs.org/patch/514331/
Could you please check if this patch (with the config options enabled) helps on your platform without DT changes?
Signed-off-by: Thomas Chou thomas@wytron.com.tw
arch/nios2/dts/3c120_devboard.dts | 171 +++++++++++++++----------------------- 1 file changed, 69 insertions(+), 102 deletions(-)
diff --git a/arch/nios2/dts/3c120_devboard.dts b/arch/nios2/dts/3c120_devboard.dts index 02524ab..70d71a5 100644 --- a/arch/nios2/dts/3c120_devboard.dts +++ b/arch/nios2/dts/3c120_devboard.dts @@ -14,6 +14,73 @@ #address-cells = <1>; #size-cells = <1>;
- aliases {
console = &jtag_uart;
- };
- timer_1ms: timer@0x400000 {
compatible = "altr,timer-1.0";
reg = <0xe8400000 0x00000020>;
interrupt-parent = <&cpu>;
interrupts = <11>;
clock-frequency = <125000000>;
u-boot,dm-pre-reloc;
- };
- jtag_uart: serial@0x4d50 {
compatible = "altr,juart-1.0";
reg = <0xe8004d50 0x00000008>;
interrupt-parent = <&cpu>;
interrupts = <1>;
u-boot,dm-pre-reloc;
- };
- tse_mac: ethernet@0x4000 {
compatible = "altr,tse-1.0";
reg = <0xe8004000 0x00000400>,
<0xe8004400 0x00000040>,
<0xe8004800 0x00000040>,
<0xe8002000 0x00002000>;
reg-names = "control_port", "rx_csr", "tx_csr", "s1";
interrupt-parent = <&cpu>;
interrupts = <2 3>;
interrupt-names = "rx_irq", "tx_irq";
rx-fifo-depth = <8192>;
tx-fifo-depth = <8192>;
max-frame-size = <1518>;
local-mac-address = [ 00 00 00 00 00 00 ];
phy-mode = "rgmii-id";
phy-handle = <&phy0>;
tse_mac_mdio: mdio {
compatible = "altr,tse-mdio";
#address-cells = <1>;
#size-cells = <0>;
phy0: ethernet-phy@18 {
reg = <18>;
device_type = "ethernet-phy";
};
};
- };
- uart: serial@0x4c80 {
compatible = "altr,uart-1.0";
reg = <0xe8004c80 0x00000020>;
interrupt-parent = <&cpu>;
interrupts = <10>;
current-speed = <115200>;
clock-frequency = <62500000>;
u-boot,dm-pre-reloc;
- };
- user_led_pio_8out: gpio@0x4cc0 {
compatible = "altr,pio-1.0";
reg = <0xe8004cc0 0x00000010>;
resetvalue = <255>;
width = <8>;
#gpio-cells = <2>;
gpio-controller;
- };
- cpus { #address-cells = <1>; #size-cells = <0>;
@@ -46,108 +113,8 @@
memory@0 { device_type = "memory";
reg = <0x10000000 0x08000000>,
<0x07fff400 0x00000400>;
reg = <0xd0000000 0x08000000>,
};<0xc7fff400 0x00000400>;
- sopc@0 {
device_type = "soc";
ranges;
#address-cells = <1>;
#size-cells = <1>;
compatible = "altr,avalon", "simple-bus";
bus-frequency = <125000000>;
pb_cpu_to_io: bridge@0x8000000 {
compatible = "simple-bus";
reg = <0x08000000 0x00800000>;
#address-cells = <1>;
#size-cells = <1>;
ranges = <0x00002000 0x08002000 0x00002000>,
<0x00004000 0x08004000 0x00000400>,
<0x00004400 0x08004400 0x00000040>,
<0x00004800 0x08004800 0x00000040>,
<0x00004c80 0x08004c80 0x00000020>,
<0x00004d50 0x08004d50 0x00000008>,
<0x00008000 0x08008000 0x00000020>,
<0x00400000 0x08400000 0x00000020>;
timer_1ms: timer@0x400000 {
compatible = "altr,timer-1.0";
reg = <0x00400000 0x00000020>;
interrupt-parent = <&cpu>;
interrupts = <11>;
clock-frequency = <125000000>;
};
timer_0: timer@0x8000 {
compatible = "altr,timer-1.0";
reg = < 0x00008000 0x00000020 >;
interrupt-parent = < &cpu >;
interrupts = < 5 >;
clock-frequency = < 125000000 >;
};
jtag_uart: serial@0x4d50 {
compatible = "altr,juart-1.0";
reg = <0x00004d50 0x00000008>;
interrupt-parent = <&cpu>;
interrupts = <1>;
};
tse_mac: ethernet@0x4000 {
compatible = "altr,tse-1.0";
reg = <0x00004000 0x00000400>,
<0x00004400 0x00000040>,
<0x00004800 0x00000040>,
<0x00002000 0x00002000>;
reg-names = "control_port", "rx_csr", "tx_csr", "s1";
interrupt-parent = <&cpu>;
interrupts = <2 3>;
interrupt-names = "rx_irq", "tx_irq";
rx-fifo-depth = <8192>;
tx-fifo-depth = <8192>;
max-frame-size = <1518>;
local-mac-address = [ 00 00 00 00 00 00 ];
phy-mode = "rgmii-id";
phy-handle = <&phy0>;
tse_mac_mdio: mdio {
compatible = "altr,tse-mdio";
#address-cells = <1>;
#size-cells = <0>;
phy0: ethernet-phy@18 {
reg = <18>;
device_type = "ethernet-phy";
};
};
};
uart: serial@0x4c80 {
compatible = "altr,uart-1.0";
reg = <0x00004c80 0x00000020>;
interrupt-parent = <&cpu>;
interrupts = <10>;
current-speed = <115200>;
clock-frequency = <62500000>;
};
};
cfi_flash_64m: flash@0x0 {
compatible = "cfi-flash";
reg = <0x00000000 0x04000000>;
bank-width = <2>;
device-width = <1>;
#address-cells = <1>;
#size-cells = <1>;
partition@800000 {
reg = <0x00800000 0x01e00000>;
label = "JFFS2 Filesystem";
};
};
- };
- chosen {
bootargs = "debug console=ttyJ0,115200";
- }; };
Thanks, Stefan

Hi Stefan,
On 09/14/2015 01:39 PM, Stefan Roese wrote:
So you are changing the DT sources for your platform because the U-Boot implementation does support the bus translation correctly (ranges properties)? I think this is the wrong approach. We need to make sure that U-Boot supports DT correctly instead. I have a patch queued to enable this. Please take a look at this thread:
Thanks a lot. So nice! This is almost the same as what I had tried but didn't work yet last day. I will try out this patch and let you know.
Best regards, Thomas Chou
participants (4)
-
Marek Vasut
-
Simon Glass
-
Stefan Roese
-
Thomas Chou