Skip to contentSkip to conversation

mips: add base support for atheros ath79 based SOCs

PATCH Superseded Wills Wang 5 participants 39 messages Dec 24, 2015 – Jan 6, 2016 1 message not in the archive

Subsystems (3)

v3 of 8 Superseded Latest is v8 →

lore
Share & tools
lore

A message that is not in the archive (sent off-list or not yet received): [email protected]

Wills Wang

author
#1 lore raw

PATCH v3 1/4 mips: add base support for atheros ath79 based SOCs

This patch enable work for ar933x SOC, tested on ar9331 board.

---

Changes in v3: None
Changes in v2: None

 arch/mips/Makefile                              |    1 +
 arch/mips/config.mk                             |    1 +
 arch/mips/mach-ath79/Makefile                   |    9 +
 arch/mips/mach-ath79/ar933x/Makefile            |    6 +
 arch/mips/mach-ath79/ar933x/ddr_tap.S           |  268 ++++++
 arch/mips/mach-ath79/ar933x/lowlevel_init.S     |  460 +++++++++
 arch/mips/mach-ath79/cpu.c                      |  269 ++++++
 arch/mips/mach-ath79/dram.c                     |   27 +
 arch/mips/mach-ath79/include/mach/ar71xx_regs.h | 1144 +++++++++++++++++++++++
 arch/mips/mach-ath79/include/mach/ar933x_uart.h |   66 ++
 arch/mips/mach-ath79/include/mach/ath79.h       |  143 +++
 arch/mips/mach-ath79/include/mach/ddr.h         |   13 +
 arch/mips/mach-ath79/reset.c                    |   55 ++
 13 files changed, 2462 insertions(+)
 create mode 100644 arch/mips/mach-ath79/Makefile
 create mode 100644 arch/mips/mach-ath79/ar933x/Makefile
 create mode 100644 arch/mips/mach-ath79/ar933x/ddr_tap.S
 create mode 100644 arch/mips/mach-ath79/ar933x/lowlevel_init.S
 create mode 100644 arch/mips/mach-ath79/cpu.c
 create mode 100644 arch/mips/mach-ath79/dram.c
 create mode 100644 arch/mips/mach-ath79/include/mach/ar71xx_regs.h
 create mode 100644 arch/mips/mach-ath79/include/mach/ar933x_uart.h
 create mode 100644 arch/mips/mach-ath79/include/mach/ath79.h
 create mode 100644 arch/mips/mach-ath79/include/mach/ddr.h
 create mode 100644 arch/mips/mach-ath79/reset.c
arch/mips/Makefile +1 -0
index 6a9f798..da5fa72 100644
@@ -8,6 +8,7 @@ libs-y += arch/mips/cpu/
 libs-y += arch/mips/lib/
 
 machine-$(CONFIG_SOC_AU1X00) += au1x00
+machine-$(CONFIG_ARCH_ATH79) += ath79
 
 machdirs := $(patsubst %,arch/mips/mach-%/,$(machine-y))
 libs-y += $(machdirs)
arch/mips/config.mk +1 -0
index 3ebc202..fd50909 100644
@@ -39,6 +39,7 @@ cpuflags-$(CONFIG_CPU_MIPS32_R1) += -march=mips32 -Wa,-mips32
 cpuflags-$(CONFIG_CPU_MIPS32_R2) += -march=mips32r2 -Wa,-mips32r2
 cpuflags-$(CONFIG_CPU_MIPS64_R1) += -march=mips64 -Wa,-mips64
 cpuflags-$(CONFIG_CPU_MIPS64_R2) += -march=mips64r2 -Wa,-mips64r2
+cpuflags-$(CONFIG_ARCH_ATH79) += -mtune=24kc
 PLATFORM_CPPFLAGS += $(cpuflags-y)
 
 PLATFORM_CPPFLAGS += -D__MIPS__
arch/mips/mach-ath79/Makefile new file +9 -0
new file mode 100644
index 0000000..bc0a41f
@@ -0,0 +1,9 @@
+#
+# SPDX-License-Identifier:	GPL-2.0+
+#
+
+obj-y += reset.o
+obj-y += cpu.o
+obj-y += dram.o
+
+obj-$(CONFIG_SOC_AR933X)	+= ar933x/
arch/mips/mach-ath79/ar933x/Makefile new file +6 -0
new file mode 100644
index 0000000..0da8fd4
@@ -0,0 +1,6 @@
+#
+# SPDX-License-Identifier:	GPL-2.0+
+#
+
+obj-y += lowlevel_init.o
+obj-y += ddr_tap.o
arch/mips/mach-ath79/ar933x/ddr_tap.S new file +268 -0

268 lines not on this page · raw message

arch/mips/mach-ath79/ar933x/lowlevel_init.S new file +460 -0

460 lines not on this page · raw message

arch/mips/mach-ath79/cpu.c new file +269 -0

269 lines not on this page · raw message

arch/mips/mach-ath79/dram.c new file +27 -0
new file mode 100644
index 0000000..42539dc
@@ -0,0 +1,27 @@
+/*
+ * (C) Copyright 2015
+ * Wills Wang, <[email protected]>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <asm/addrspace.h>
+#include <asm/arch/ddr.h>
+
+phys_size_t initdram(int board_type)
+{
+	uint8_t *addr, *p;
+	int i;
+
+	ddr_tap_init();
+	addr = (uint8_t *)KSEG1;
+	*addr = 0x77;
+	for (i = 0, p = addr; p < (uint8_t *)KSEG2; i++) {
+		p += 0x1000000;
+		*p = i;
+		if (*addr != 0x77)
+			break;
+	}
+	return (phys_size_t)(p - addr);
+}
arch/mips/mach-ath79/include/mach/ar71xx_regs.h new file +1144 -0

1,144 lines not on this page · raw message

arch/mips/mach-ath79/include/mach/ar933x_uart.h new file +66 -0

66 lines not on this page · raw message

arch/mips/mach-ath79/include/mach/ath79.h new file +143 -0

143 lines not on this page · raw message

arch/mips/mach-ath79/include/mach/ddr.h new file +13 -0
new file mode 100644
index 0000000..e90c9a1
@@ -0,0 +1,13 @@
+/*
+ * (C) Copyright 2015
+ * Wills Wang, <[email protected]>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef __ASM_MACH_DDR_H
+#define __ASM_MACH_DDR_H
+
+void ddr_tap_init(void);
+
+#endif /* __ASM_MACH_DDR_H */
arch/mips/mach-ath79/reset.c new file +55 -0

55 lines not on this page · raw message

Signature · 1 line
1.9.1
#2 lore raw

PATCH v3 1/4 mips: add base support for atheros ath79 based SOCs

Quoted 3 lines · Wills Wang

This patch enable work for ar933x SOC, tested on ar9331 board.

[...]

arch/mips/config.mk cpuflags-$(CONFIG_CPU_MIPS32_R1) += -march=mips32 · line 40

Quoted 10 lines
arch/mips/config.mk +1 -3
index 3ebc202..fd50909 100644
@@ -39,6 +39,7 @@ cpuflags-$(CONFIG_CPU_MIPS32_R1) += -march=mips32
-Wa,-mips32 cpuflags-$(CONFIG_CPU_MIPS32_R2) += -march=mips32r2
-Wa,-mips32r2 cpuflags-$(CONFIG_CPU_MIPS64_R1) += -march=mips64
-Wa,-mips64
 cpuflags-$(CONFIG_CPU_MIPS64_R2) += -march=mips64r2 -Wa,-mips64r2
+cpuflags-$(CONFIG_ARCH_ATH79) += -mtune=24kc

You can just tune it for MIPS32_R2 , it will be compatible with older toolchains too. I don't think there is much benefit in being so explicit and using mips24kc tuning.

Quoted 3 lines
arch/mips/config.mk +0 -0
 PLATFORM_CPPFLAGS += $(cpuflags-y)
 
 PLATFORM_CPPFLAGS += -D__MIPS__

[...]

Quoted 39 lines
(quoted diff) +0 -0

b/arch/mips/mach-ath79/ar933x/ddr_tap.S new file mode 100644 index 0000000..18c57de

arch/mips/mach-ath79/ar933x/ddr_tap.S new file +33 -0
@@ -0,0 +1,268 @@
+/*
+ * (C) Copyright 2015
+ * Wills Wang, <[email protected]>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <config.h>
+#include <asm/asm.h>
+#include <asm/regdef.h>
+#include <asm/mipsregs.h>
+#include <asm/addrspace.h>
+#include <asm/arch/ar71xx_regs.h>
+
+#define DRAM_K0(x)      KSEG0ADDR(x)
+#define DRAM_K1(x)      KSEG1ADDR(x)
+
+	.text
+	.set noreorder
+
+LEAF(ddr_tap_init)
+	/* Tap settings for the DDR */
+	li      t0, 0xffffffff
+	li      t1, DRAM_K0(0x500000)
+	sw      t0, 0x0(t1)
+	sw      t0, 0x4(t1)
+	sw      t0, 0x8(t1)
+	sw      t0, 0xc(t1)
+	nop
+	nop
+
+	li      t8, DRAM_K1(0x2000)
+	li      t0, 0x00

arch/mips/mach-ath79/ar933x/ddr_tap.S line 43

Quoted 10 lines
arch/mips/mach-ath79/ar933x/ddr_tap.S new file +10 -0
+	li      t1, 0x100
+0:
+	andi    t2, t0, 0x03
+	li      t3, 0x00
+	bne     t2, t3,1f
+	 nop
+	li      t9, 0x00000000
+	sw      t9, 0x0(t8)
+	b       2f
+	 nop

Please rewrite this into C, I believe it should be pretty easy.

[...]

Quoted 90 lines
(quoted diff) +0 -0

b/arch/mips/mach-ath79/ar933x/lowlevel_init.S new file mode 100644 index 0000000..72509ca

arch/mips/mach-ath79/ar933x/lowlevel_init.S new file +84 -0
@@ -0,0 +1,460 @@
+/*
+ * (C) Copyright 2015
+ * Wills Wang, <[email protected]>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <config.h>
+#include <asm/asm.h>
+#include <asm/regdef.h>
+#include <asm/mipsregs.h>
+#include <asm/addrspace.h>
+#include <asm/arch/ar71xx_regs.h>
+
+#define SET_BIT(val, bit)   ((val) | (1 << (bit)))
+#define SET_PLL_PD(val)     SET_BIT(val, 30)
+#define AHB_DIV_TO_4(val)   SET_BIT(SET_BIT(val, 15), 16)
+#define PLL_BYPASS(val)     SET_BIT(val, 2)
+
+#define MK_PLL_CONF(divint, refdiv, range, outdiv) \
+     (((0x3F & divint) << 10) | \
+     ((0x1F & refdiv) << 16) | \
+     ((0x1 & range)   << 21) | \
+     ((0x7 & outdiv)  << 23) )
+
+#define MK_CLK_CNTL(cpudiv, ddrdiv, ahbdiv) \
+    (((0x3 & (cpudiv - 1)) << 5)  | \
+    ((0x3 & (ddrdiv - 1)) << 10) | \
+    ((0x3 & (ahbdiv - 1)) << 15) )
+
+/*
+ * PLL_CPU_CONFIG_VAL
+ *
+ * Bit30 is set (CPU_PLLPWD = 1 -> power down control for CPU PLL)
+ * After PLL configuration we need to clear this bit
+ *
+ * Values written into CPU PLL Configuration (CPU_PLL_CONFIG)
+ *
+ * bits 10..15  (6bit)  DIV_INT (Integer part of the DIV to CPU PLL)
+ *                      =>  32  (0x20)  VCOOUT = XTAL * DIV_INT
+ * bits 16..20  (5bit)  REFDIV  (Reference clock divider)
+ *                      =>  1   (0x1)   [Must start at values 1]
+ * bits 21      (1bit)  RANGE   (VCO frequency range of the CPU PLL)
+ *                      =>  0   (0x0)   [Doesn't impact clock values]
+ * bits 23..25  (3bit)  OUTDIV  (Ratio between VCO and PLL output)
+ *                      =>  1   (0x1)   [0 is illegal!]
+ *                              PLLOUT = VCOOUT * (1/2^OUTDIV)
+ */
+/* DIV_INT=32 (25MHz*32/2=400MHz), REFDIV=1, RANGE=0, OUTDIV=1 */
+#define PLL_CPU_CONFIG_VAL_40M  MK_PLL_CONF(20, 1, 0, 1)
+/* DIV_INT=20 (40MHz*20/2=400MHz), REFDIV=1, RANGE=0, OUTDIV=1 */
+#define PLL_CPU_CONFIG_VAL_25M  MK_PLL_CONF(32, 1, 0, 1)
+
+/*
+ * PLL_CLK_CONTROL_VAL
+ *
+ * In PLL_CLK_CONTROL_VAL bit 2 is set (BYPASS = 1 -> bypass PLL)
+ * After PLL configuration we need to clear this bit
+ *
+ * Values written into CPU Clock Control Register CLOCK_CONTROL
+ *
+ * bits 2       (1bit)  BYPASS (Bypass PLL. This defaults to 1 for test.
+ *                      Software must enable the CPU PLL for normal and
+ *                      then set this bit to 0)
+ * bits 5..6    (2bit)  CPU_POST_DIV    =>  0   (DEFAULT, Ratio = 1)
+ *                      CPU_CLK = PLLOUT / CPU_POST_DIV
+ * bits 10..11  (2bit)  DDR_POST_DIV    =>  0   (DEFAULT, Ratio = 1)
+ *                      DDR_CLK = PLLOUT / DDR_POST_DIV
+ * bits 15..16  (2bit)  AHB_POST_DIV    =>  1   (DEFAULT, Ratio = 2)
+ *                      AHB_CLK = PLLOUT / AHB_POST_DIV
+ *
+ */
+#define PLL_CLK_CONTROL_VAL MK_CLK_CNTL(1, 1, 2)
+
+    .text
+    .set noreorder
+
+LEAF(lowlevel_init)
+   /* These three WLAN_RESET will avoid original issue */
+    li      t3, 0x03
+1:
+    li      t0, KSEG1ADDR(AR71XX_RESET_BASE)
+    lw      t1, AR933X_RESET_REG_RESET_MODULE(t0)
+    ori     t1, t1, 0x0800

arch/mips/mach-ath79/ar933x/lowlevel_init.S line 94

Quoted 10 lines
arch/mips/mach-ath79/ar933x/lowlevel_init.S new file +10 -0
+    sw      t1, AR933X_RESET_REG_RESET_MODULE(t0)
+    nop
+    lw      t1, AR933X_RESET_REG_RESET_MODULE(t0)
+    li      t2, 0xfffff7ff
+    and     t1, t1, t2
+    sw      t1, AR933X_RESET_REG_RESET_MODULE(t0)
+    nop
+    addi    t3, t3, -1
+    bnez    t3, 1b
+     nop

This should be also easy to rewrite into C , right ?

[...]

Quoted 27 lines
arch/mips/mach-ath79/cpu.c new file +21 -0
new file mode 100644
index 0000000..1f58877
@@ -0,0 +1,269 @@
+/*
+ * (C) Copyright 2015
+ * Wills Wang, <[email protected]>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/addrspace.h>
+#include <asm/types.h>
+#include <asm/arch/ath79.h>
+#include <asm/arch/ar71xx_regs.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+enum ath79_soc_type get_soc_type(void)
+{
+	enum ath79_soc_type soc = ATH79_SOC_UNKNOWN;
+	u32 id, major, minor;
+

arch/mips/mach-ath79/cpu.c line 31

Quoted 10 lines
arch/mips/mach-ath79/cpu.c new file +10 -0
+	id = readl(KSEG1ADDR(AR71XX_RESET_BASE + AR71XX_RESET_REG_REV_ID));
+	major = id & REV_ID_MAJOR_MASK;
+
+	switch (major) {
+	case REV_ID_MAJOR_AR71XX:
+		minor = id & AR71XX_REV_ID_MINOR_MASK;
+		switch (minor) {
+		case AR71XX_REV_ID_MINOR_AR7130:
+			soc = ATH79_SOC_AR7130;
+			break;

I think you can convert this stuff into a table of sorts, so you won't have such a lengthy code:

struct {
	u32 major;
	u32 minor;
	enum soc;
} table[] {
	{ REV_ID_MAJOR_AR71XX, AR71XX_REV_ID_MINOR_AR7130, ATH79_SOC_AR7130 },
        ...
}

And just iterate over such table.

[...]

Quoted 11 lines
arch/mips/mach-ath79/cpu.c new file +11 -0
+int print_cpuinfo(void)
+{
+	enum ath79_soc_type soc = ATH79_SOC_UNKNOWN;
+	char *chip = "????";
+	u32 id, major, minor;
+	u32 rev = 0;
+	u32 ver = 1;
+
+	id = readl(KSEG1ADDR(AR71XX_RESET_BASE + AR71XX_RESET_REG_REV_ID));
+	major = id & REV_ID_MAJOR_MASK;
+

arch/mips/mach-ath79/cpu.c line 137

Quoted 10 lines
arch/mips/mach-ath79/cpu.c new file +10 -0
+	switch (major) {
+	case REV_ID_MAJOR_AR71XX:
+		minor = id & AR71XX_REV_ID_MINOR_MASK;
+		rev = id >> AR71XX_REV_ID_REVISION_SHIFT;
+		rev &= AR71XX_REV_ID_REVISION_MASK;
+		switch (minor) {
+		case AR71XX_REV_ID_MINOR_AR7130:
+			soc = ATH79_SOC_AR7130;
+			chip = "7130";
+			break;

DTTO here, use table lookup

[...]

Quoted 24 lines
arch/mips/mach-ath79/cpu.c new file +3 -0
+
+	return 0;
+}
arch/mips/mach-ath79/dram.c new file +15 -0
new file mode 100644
index 0000000..42539dc
@@ -0,0 +1,27 @@
+/*
+ * (C) Copyright 2015
+ * Wills Wang, <[email protected]>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <asm/addrspace.h>
+#include <asm/arch/ddr.h>
+
+phys_size_t initdram(int board_type)
+{
+	uint8_t *addr, *p;
+	int i;

arch/mips/mach-ath79/dram.c line 25

Quoted 10 lines
arch/mips/mach-ath79/dram.c new file +10 -0
+
+	ddr_tap_init();
+	addr = (uint8_t *)KSEG1;
+	*addr = 0x77;
+	for (i = 0, p = addr; p < (uint8_t *)KSEG2; i++) {
+		p += 0x1000000;
+		*p = i;
+		if (*addr != 0x77)
+			break;
+	}

What is this and how does it work ?

Quoted 2 lines
arch/mips/mach-ath79/dram.c new file +2 -0
+	return (phys_size_t)(p - addr);
+}

[...]

Quoted 14 lines
arch/mips/mach-ath79/reset.c new file +8 -0
new file mode 100644
index 0000000..0ace05d
@@ -0,0 +1,55 @@
+/*
+ * (C) Copyright 2015
+ * Wills Wang, <[email protected]>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>

arch/mips/mach-ath79/reset.c line 18

Quoted 10 lines
arch/mips/mach-ath79/reset.c new file +10 -0
+#include <asm/io.h>
+#include <asm/addrspace.h>
+#include <asm/types.h>
+#include <asm/arch/ath79.h>
+#include <asm/arch/ar71xx_regs.h>
+
+#define REG_READ(b, o)      readl(KSEG1ADDR(b + o))
+#define REG_WRITE(b, o, v)  writel(v, KSEG1ADDR((b + o)))
+#define RST_READ(a)        REG_READ(AR71XX_RESET_BASE, a)
+#define RST_WRITE(a, v)    REG_WRITE(AR71XX_RESET_BASE, a, v)

Drop these.

Quoted 21 lines
arch/mips/mach-ath79/reset.c new file +21 -0
+DECLARE_GLOBAL_DATA_PTR;
+
+void _machine_restart(void)
+{
+	enum ath79_soc_type soc;
+	u32 val, reg = 0;
+
+	soc = get_soc_type();
+	if (soc_is_ar71xx(soc))
+		reg = AR71XX_RESET_REG_RESET_MODULE;
+	else if (soc_is_ar724x(soc))
+		reg = AR724X_RESET_REG_RESET_MODULE;
+	else if (soc_is_ar913x(soc))
+		reg = AR913X_RESET_REG_RESET_MODULE;
+	else if (soc_is_ar933x(soc))
+		reg = AR933X_RESET_REG_RESET_MODULE;
+	else if (soc_is_ar934x(soc))
+		reg = AR934X_RESET_REG_RESET_MODULE;
+	else if (soc_is_qca953x(soc))
+		reg = QCA953X_RESET_REG_RESET_MODULE;
+	else if (soc_is_qca955x(soc))

arch/mips/mach-ath79/reset.c line 50

Quoted 10 lines
arch/mips/mach-ath79/reset.c new file +10 -0
+		reg = QCA955X_RESET_REG_RESET_MODULE;
+	else if (soc_is_qca956x(soc))
+		reg = QCA956X_RESET_REG_RESET_MODULE;
+	else
+		puts("Reset register not defined for this SOC\n");
+
+	if (reg) {
+		val = RST_READ(reg);
+		val |= AR71XX_RESET_FULL_CHIP;
+		RST_WRITE(reg, val);

setbits_le32() please.

Quoted 5 lines
arch/mips/mach-ath79/reset.c new file +5 -0
+	}
+
+	while (1)
+		/* NOP */;
+}
author
#3 lore raw

PATCH v3 1/4 mips: add base support for atheros ath79 based SOCs

Quoted 171 lines · Marek Vasut
Quoted 3 lines · Wills Wang

This patch enable work for ar933x SOC, tested on ar9331 board.

[...]

arch/mips/config.mk cpuflags-$(CONFIG_CPU_MIPS32_R1) += -march=mips32 · line 40

Quoted 10 lines
arch/mips/config.mk +1 -3
index 3ebc202..fd50909 100644
@@ -39,6 +39,7 @@ cpuflags-$(CONFIG_CPU_MIPS32_R1) += -march=mips32
-Wa,-mips32 cpuflags-$(CONFIG_CPU_MIPS32_R2) += -march=mips32r2
-Wa,-mips32r2 cpuflags-$(CONFIG_CPU_MIPS64_R1) += -march=mips64
-Wa,-mips64
  cpuflags-$(CONFIG_CPU_MIPS64_R2) += -march=mips64r2 -Wa,-mips64r2
+cpuflags-$(CONFIG_ARCH_ATH79) += -mtune=24kc

You can just tune it for MIPS32_R2 , it will be compatible with older toolchains too. I don't think there is much benefit in being so explicit and using mips24kc tuning.

Quoted 3 lines
arch/mips/config.mk +0 -0
  PLATFORM_CPPFLAGS += $(cpuflags-y)
 
  PLATFORM_CPPFLAGS += -D__MIPS__

[...]

Quoted 39 lines
(quoted diff) +0 -0

b/arch/mips/mach-ath79/ar933x/ddr_tap.S new file mode 100644 index 0000000..18c57de

arch/mips/mach-ath79/ar933x/ddr_tap.S new file +33 -0
@@ -0,0 +1,268 @@
+/*
+ * (C) Copyright 2015
+ * Wills Wang, <[email protected]>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <config.h>
+#include <asm/asm.h>
+#include <asm/regdef.h>
+#include <asm/mipsregs.h>
+#include <asm/addrspace.h>
+#include <asm/arch/ar71xx_regs.h>
+
+#define DRAM_K0(x)      KSEG0ADDR(x)
+#define DRAM_K1(x)      KSEG1ADDR(x)
+
+	.text
+	.set noreorder
+
+LEAF(ddr_tap_init)
+	/* Tap settings for the DDR */
+	li      t0, 0xffffffff
+	li      t1, DRAM_K0(0x500000)
+	sw      t0, 0x0(t1)
+	sw      t0, 0x4(t1)
+	sw      t0, 0x8(t1)
+	sw      t0, 0xc(t1)
+	nop
+	nop
+
+	li      t8, DRAM_K1(0x2000)
+	li      t0, 0x00

arch/mips/mach-ath79/ar933x/ddr_tap.S line 43

Quoted 10 lines
arch/mips/mach-ath79/ar933x/ddr_tap.S new file +10 -0
+	li      t1, 0x100
+0:
+	andi    t2, t0, 0x03
+	li      t3, 0x00
+	bne     t2, t3,1f
+	 nop
+	li      t9, 0x00000000
+	sw      t9, 0x0(t8)
+	b       2f
+	 nop

Please rewrite this into C, I believe it should be pretty easy.

[...]

Quoted 93 lines
(quoted diff) +0 -0

b/arch/mips/mach-ath79/ar933x/lowlevel_init.S new file mode 100644 index 0000000..72509ca

arch/mips/mach-ath79/ar933x/lowlevel_init.S new file +87 -0
@@ -0,0 +1,460 @@
+/*
+ * (C) Copyright 2015
+ * Wills Wang, <[email protected]>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <config.h>
+#include <asm/asm.h>
+#include <asm/regdef.h>
+#include <asm/mipsregs.h>
+#include <asm/addrspace.h>
+#include <asm/arch/ar71xx_regs.h>
+
+#define SET_BIT(val, bit)   ((val) | (1 << (bit)))
+#define SET_PLL_PD(val)     SET_BIT(val, 30)
+#define AHB_DIV_TO_4(val)   SET_BIT(SET_BIT(val, 15), 16)
+#define PLL_BYPASS(val)     SET_BIT(val, 2)
+
+#define MK_PLL_CONF(divint, refdiv, range, outdiv) \
+     (((0x3F & divint) << 10) | \
+     ((0x1F & refdiv) << 16) | \
+     ((0x1 & range)   << 21) | \
+     ((0x7 & outdiv)  << 23) )
+
+#define MK_CLK_CNTL(cpudiv, ddrdiv, ahbdiv) \
+    (((0x3 & (cpudiv - 1)) << 5)  | \
+    ((0x3 & (ddrdiv - 1)) << 10) | \
+    ((0x3 & (ahbdiv - 1)) << 15) )
+
+/*
+ * PLL_CPU_CONFIG_VAL
+ *
+ * Bit30 is set (CPU_PLLPWD = 1 -> power down control for CPU PLL)
+ * After PLL configuration we need to clear this bit
+ *
+ * Values written into CPU PLL Configuration (CPU_PLL_CONFIG)
+ *
+ * bits 10..15  (6bit)  DIV_INT (Integer part of the DIV to CPU PLL)
+ *                      =>  32  (0x20)  VCOOUT = XTAL * DIV_INT
+ * bits 16..20  (5bit)  REFDIV  (Reference clock divider)
+ *                      =>  1   (0x1)   [Must start at values 1]
+ * bits 21      (1bit)  RANGE   (VCO frequency range of the CPU PLL)
+ *                      =>  0   (0x0)   [Doesn't impact clock values]
+ * bits 23..25  (3bit)  OUTDIV  (Ratio between VCO and PLL output)
+ *                      =>  1   (0x1)   [0 is illegal!]
+ *                              PLLOUT = VCOOUT * (1/2^OUTDIV)
+ */
+/* DIV_INT=32 (25MHz*32/2=400MHz), REFDIV=1, RANGE=0, OUTDIV=1 */
+#define PLL_CPU_CONFIG_VAL_40M  MK_PLL_CONF(20, 1, 0, 1)
+/* DIV_INT=20 (40MHz*20/2=400MHz), REFDIV=1, RANGE=0, OUTDIV=1 */
+#define PLL_CPU_CONFIG_VAL_25M  MK_PLL_CONF(32, 1, 0, 1)
+
+/*
+ * PLL_CLK_CONTROL_VAL
+ *
+ * In PLL_CLK_CONTROL_VAL bit 2 is set (BYPASS = 1 -> bypass PLL)
+ * After PLL configuration we need to clear this bit
+ *
+ * Values written into CPU Clock Control Register CLOCK_CONTROL
+ *
+ * bits 2       (1bit)  BYPASS (Bypass PLL. This defaults to 1 for test.
+ *                      Software must enable the CPU PLL for normal and
+ *                      then set this bit to 0)
+ * bits 5..6    (2bit)  CPU_POST_DIV    =>  0   (DEFAULT, Ratio = 1)
+ *                      CPU_CLK = PLLOUT / CPU_POST_DIV
+ * bits 10..11  (2bit)  DDR_POST_DIV    =>  0   (DEFAULT, Ratio = 1)
+ *                      DDR_CLK = PLLOUT / DDR_POST_DIV
+ * bits 15..16  (2bit)  AHB_POST_DIV    =>  1   (DEFAULT, Ratio = 2)
+ *                      AHB_CLK = PLLOUT / AHB_POST_DIV
+ *
+ */
+#define PLL_CLK_CONTROL_VAL MK_CLK_CNTL(1, 1, 2)
+
+    .text
+    .set noreorder
+
+LEAF(lowlevel_init)
+   /* These three WLAN_RESET will avoid original issue */
+    li      t3, 0x03
+1:
+    li      t0, KSEG1ADDR(AR71XX_RESET_BASE)
+    lw      t1, AR933X_RESET_REG_RESET_MODULE(t0)
+    ori     t1, t1, 0x0800
+    sw      t1, AR933X_RESET_REG_RESET_MODULE(t0)
+    nop
+    lw      t1, AR933X_RESET_REG_RESET_MODULE(t0)
Quoted 8 lines

arch/mips/mach-ath79/ar933x/lowlevel_init.S line 94

Quoted 7 lines
arch/mips/mach-ath79/ar933x/lowlevel_init.S new file +7 -0
+    li      t2, 0xfffff7ff
+    and     t1, t1, t2
+    sw      t1, AR933X_RESET_REG_RESET_MODULE(t0)
+    nop
+    addi    t3, t3, -1
+    bnez    t3, 1b
+     nop

This should be also easy to rewrite into C , right ?

C runtime environment is not available.
C stack is not ready before DDR has initialized.

Quoted 108 lines

[...]

Quoted 27 lines
arch/mips/mach-ath79/cpu.c new file +21 -0
new file mode 100644
index 0000000..1f58877
@@ -0,0 +1,269 @@
+/*
+ * (C) Copyright 2015
+ * Wills Wang, <[email protected]>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/addrspace.h>
+#include <asm/types.h>
+#include <asm/arch/ath79.h>
+#include <asm/arch/ar71xx_regs.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+enum ath79_soc_type get_soc_type(void)
+{
+	enum ath79_soc_type soc = ATH79_SOC_UNKNOWN;
+	u32 id, major, minor;
+

arch/mips/mach-ath79/cpu.c line 31

Quoted 10 lines
arch/mips/mach-ath79/cpu.c new file +10 -0
+	id = readl(KSEG1ADDR(AR71XX_RESET_BASE + AR71XX_RESET_REG_REV_ID));
+	major = id & REV_ID_MAJOR_MASK;
+
+	switch (major) {
+	case REV_ID_MAJOR_AR71XX:
+		minor = id & AR71XX_REV_ID_MINOR_MASK;
+		switch (minor) {
+		case AR71XX_REV_ID_MINOR_AR7130:
+			soc = ATH79_SOC_AR7130;
+			break;

I think you can convert this stuff into a table of sorts, so you won't have such a lengthy code:

struct {
	u32 major;
	u32 minor;
	enum soc;
} table[] {
	{ REV_ID_MAJOR_AR71XX, AR71XX_REV_ID_MINOR_AR7130, ATH79_SOC_AR7130 },
         ...
}

And just iterate over such table.

[...]

Quoted 11 lines
arch/mips/mach-ath79/cpu.c new file +11 -0
+int print_cpuinfo(void)
+{
+	enum ath79_soc_type soc = ATH79_SOC_UNKNOWN;
+	char *chip = "????";
+	u32 id, major, minor;
+	u32 rev = 0;
+	u32 ver = 1;
+
+	id = readl(KSEG1ADDR(AR71XX_RESET_BASE + AR71XX_RESET_REG_REV_ID));
+	major = id & REV_ID_MAJOR_MASK;
+

arch/mips/mach-ath79/cpu.c line 137

Quoted 10 lines
arch/mips/mach-ath79/cpu.c new file +10 -0
+	switch (major) {
+	case REV_ID_MAJOR_AR71XX:
+		minor = id & AR71XX_REV_ID_MINOR_MASK;
+		rev = id >> AR71XX_REV_ID_REVISION_SHIFT;
+		rev &= AR71XX_REV_ID_REVISION_MASK;
+		switch (minor) {
+		case AR71XX_REV_ID_MINOR_AR7130:
+			soc = ATH79_SOC_AR7130;
+			chip = "7130";
+			break;

DTTO here, use table lookup

[...]

Quoted 27 lines
arch/mips/mach-ath79/cpu.c new file +3 -0
+
+	return 0;
+}
arch/mips/mach-ath79/dram.c new file +18 -0
new file mode 100644
index 0000000..42539dc
@@ -0,0 +1,27 @@
+/*
+ * (C) Copyright 2015
+ * Wills Wang, <[email protected]>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <asm/addrspace.h>
+#include <asm/arch/ddr.h>
+
+phys_size_t initdram(int board_type)
+{
+	uint8_t *addr, *p;
+	int i;
+
+	ddr_tap_init();
+	addr = (uint8_t *)KSEG1;
Quoted 8 lines

arch/mips/mach-ath79/dram.c line 25

Quoted 7 lines
arch/mips/mach-ath79/dram.c new file +7 -0
+	*addr = 0x77;
+	for (i = 0, p = addr; p < (uint8_t *)KSEG2; i++) {
+		p += 0x1000000;
+		*p = i;
+		if (*addr != 0x77)
+			break;
+	}

What is this and how does it work ?

Physical memory was mapped circularly for this chip.

Quoted 55 lines
Quoted 3 lines
arch/mips/mach-ath79/dram.c new file +2 -0
+	return (phys_size_t)(p - addr);
+}

[...]

Quoted 14 lines
arch/mips/mach-ath79/reset.c new file +8 -0
new file mode 100644
index 0000000..0ace05d
@@ -0,0 +1,55 @@
+/*
+ * (C) Copyright 2015
+ * Wills Wang, <[email protected]>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>

arch/mips/mach-ath79/reset.c line 18

Quoted 10 lines
arch/mips/mach-ath79/reset.c new file +10 -0
+#include <asm/io.h>
+#include <asm/addrspace.h>
+#include <asm/types.h>
+#include <asm/arch/ath79.h>
+#include <asm/arch/ar71xx_regs.h>
+
+#define REG_READ(b, o)      readl(KSEG1ADDR(b + o))
+#define REG_WRITE(b, o, v)  writel(v, KSEG1ADDR((b + o)))
+#define RST_READ(a)        REG_READ(AR71XX_RESET_BASE, a)
+#define RST_WRITE(a, v)    REG_WRITE(AR71XX_RESET_BASE, a, v)

Drop these.

Quoted 24 lines
arch/mips/mach-ath79/reset.c new file +24 -0
+DECLARE_GLOBAL_DATA_PTR;
+
+void _machine_restart(void)
+{
+	enum ath79_soc_type soc;
+	u32 val, reg = 0;
+
+	soc = get_soc_type();
+	if (soc_is_ar71xx(soc))
+		reg = AR71XX_RESET_REG_RESET_MODULE;
+	else if (soc_is_ar724x(soc))
+		reg = AR724X_RESET_REG_RESET_MODULE;
+	else if (soc_is_ar913x(soc))
+		reg = AR913X_RESET_REG_RESET_MODULE;
+	else if (soc_is_ar933x(soc))
+		reg = AR933X_RESET_REG_RESET_MODULE;
+	else if (soc_is_ar934x(soc))
+		reg = AR934X_RESET_REG_RESET_MODULE;
+	else if (soc_is_qca953x(soc))
+		reg = QCA953X_RESET_REG_RESET_MODULE;
+	else if (soc_is_qca955x(soc))
+		reg = QCA955X_RESET_REG_RESET_MODULE;
+	else if (soc_is_qca956x(soc))
+		reg = QCA956X_RESET_REG_RESET_MODULE;
Quoted 8 lines

arch/mips/mach-ath79/reset.c line 50

Quoted 7 lines
arch/mips/mach-ath79/reset.c new file +7 -0
+	else
+		puts("Reset register not defined for this SOC\n");
+
+	if (reg) {
+		val = RST_READ(reg);
+		val |= AR71XX_RESET_FULL_CHIP;
+		RST_WRITE(reg, val);

setbits_le32() please.

Macro setbits_le32() is not available for MIPS architecture. Other, I don't think there is better in being so explicit and using little-endian.

Quoted 6 lines
Quoted 5 lines
arch/mips/mach-ath79/reset.c new file +5 -0
+	}
+
+	while (1)
+		/* NOP */;
+}
#4 lore raw

PATCH v3 1/4 mips: add base support for atheros ath79 based SOCs

On Thursday, December 24, 2015 at 02:51:06 PM, Wills Wang wrote:

[...]

Quoted 18 lines
Quoted 18 lines
Quoted 17 lines
arch/mips/mach-ath79/ar933x/lowlevel_init.S new file +17 -0
+LEAF(lowlevel_init)
+   /* These three WLAN_RESET will avoid original issue */
+    li      t3, 0x03
+1:
+    li      t0, KSEG1ADDR(AR71XX_RESET_BASE)
+    lw      t1, AR933X_RESET_REG_RESET_MODULE(t0)
+    ori     t1, t1, 0x0800
+    sw      t1, AR933X_RESET_REG_RESET_MODULE(t0)
+    nop
+    lw      t1, AR933X_RESET_REG_RESET_MODULE(t0)
+    li      t2, 0xfffff7ff
+    and     t1, t1, t2
+    sw      t1, AR933X_RESET_REG_RESET_MODULE(t0)
+    nop
+    addi    t3, t3, -1
+    bnez    t3, 1b
+     nop
Quoted 4 lines
Quoted 1 line

This should be also easy to rewrite into C , right ?

C runtime environment is not available.
C stack is not ready before DDR has initialized.

Just point the stack into a locked cacheline or some onchip RAM and there you have a C runtime. That should be pretty easy :)

[...]

Quoted 17 lines
Quoted 8 lines
Quoted 8 lines
arch/mips/mach-ath79/dram.c new file +8 -0
+phys_size_t initdram(int board_type)
+{
+	uint8_t *addr, *p;
+	int i;
+
+	ddr_tap_init();
+	addr = (uint8_t *)KSEG1;
+	*addr = 0x77;
Quoted 8 lines

arch/mips/mach-ath79/dram.c line 25

Quoted 6 lines
arch/mips/mach-ath79/dram.c new file +6 -0
+	for (i = 0, p = addr; p < (uint8_t *)KSEG2; i++) {
+		p += 0x1000000;
+		*p = i;
+		if (*addr != 0x77)
+			break;
+	}

What is this and how does it work ?

Quoted 1 line

Physical memory was mapped circularly for this chip.

Can you please expand on that ? I am not as deep in this chip as you are, so please explain it to me in a bit more detail.

Quoted 3 lines
Quoted 3 lines
Quoted 2 lines
arch/mips/mach-ath79/dram.c new file +2 -0
+	return (phys_size_t)(p - addr);
+}

[...]

Quoted 8 lines
Quoted 6 lines

arch/mips/mach-ath79/reset.c line 50

Quoted 4 lines
arch/mips/mach-ath79/reset.c new file +4 -0
+	if (reg) {
+		val = RST_READ(reg);
+		val |= AR71XX_RESET_FULL_CHIP;
+		RST_WRITE(reg, val);

setbits_le32() please.

Macro setbits_le32() is not available for MIPS architecture.

You can always add them :)

Quoted 2 lines

Other, I don't think there is better in being so explicit and using little-endian.

I believe your register accesses should have correct endianness exactly beause mips can be both endian.

author
#5 lore raw

PATCH v3 1/4 mips: add base support for atheros ath79 based SOCs

Quoted 21 lines · Marek Vasut

On Thursday, December 24, 2015 at 02:51:06 PM, Wills Wang wrote:

[...]

Quoted 17 lines
Quoted 17 lines
Quoted 17 lines
arch/mips/mach-ath79/ar933x/lowlevel_init.S new file +17 -0
+LEAF(lowlevel_init)
+   /* These three WLAN_RESET will avoid original issue */
+    li      t3, 0x03
+1:
+    li      t0, KSEG1ADDR(AR71XX_RESET_BASE)
+    lw      t1, AR933X_RESET_REG_RESET_MODULE(t0)
+    ori     t1, t1, 0x0800
+    sw      t1, AR933X_RESET_REG_RESET_MODULE(t0)
+    nop
+    lw      t1, AR933X_RESET_REG_RESET_MODULE(t0)
+    li      t2, 0xfffff7ff
+    and     t1, t1, t2
+    sw      t1, AR933X_RESET_REG_RESET_MODULE(t0)
+    nop
+    addi    t3, t3, -1
+    bnez    t3, 1b
+     nop
Quoted 5 lines
Quoted 3 lines
Quoted 1 line

This should be also easy to rewrite into C , right ?

C runtime environment is not available.
C stack is not ready before DDR has initialized.

Just point the stack into a locked cacheline or some onchip RAM and there you have a C runtime. That should be pretty easy :)

How to lock cacheline?
My guess is that cache memory may be use to map SPI flash at 0x9f000000 by ROM code.

Quoted 30 lines

[...]

Quoted 15 lines
Quoted 7 lines
Quoted 7 lines
arch/mips/mach-ath79/dram.c new file +7 -0
+phys_size_t initdram(int board_type)
+{
+	uint8_t *addr, *p;
+	int i;
+
+	ddr_tap_init();
+	addr = (uint8_t *)KSEG1;
Quoted 8 lines

arch/mips/mach-ath79/dram.c line 25

Quoted 7 lines
arch/mips/mach-ath79/dram.c new file +7 -0
+	*addr = 0x77;
+	for (i = 0, p = addr; p < (uint8_t *)KSEG2; i++) {
+		p += 0x1000000;
+		*p = i;
+		if (*addr != 0x77)
+			break;
+	}

What is this and how does it work ?

Quoted 1 line

Physical memory was mapped circularly for this chip.

Can you please expand on that ? I am not as deep in this chip as you are, so please explain it to me in a bit more detail.

Quoted 2 lines
Quoted 2 lines
Quoted 2 lines
arch/mips/mach-ath79/dram.c new file +2 -0
+	return (phys_size_t)(p - addr);
+}

[...]

Quoted 5 lines
Quoted 5 lines

arch/mips/mach-ath79/reset.c line 50

Quoted 4 lines
arch/mips/mach-ath79/reset.c new file +4 -0
+	if (reg) {
+		val = RST_READ(reg);
+		val |= AR71XX_RESET_FULL_CHIP;
+		RST_WRITE(reg, val);

setbits_le32() please.

Quoted 9 lines
Quoted 1 line

Macro setbits_le32() is not available for MIPS architecture.

You can always add them :)

Quoted 2 lines

Other, I don't think there is better in being so explicit and using little-endian.

I believe your register accesses should have correct endianness exactly beause mips can be both endian.

What is the advantage of using setbits_le32()?

#6 lore raw

PATCH v3 1/4 mips: add base support for atheros ath79 based SOCs

Quoted 25 lines · Wills Wang
Quoted 24 lines · Marek Vasut

On Thursday, December 24, 2015 at 02:51:06 PM, Wills Wang wrote:

[...]

Quoted 20 lines
Quoted 19 lines
Quoted 7 lines
arch/mips/mach-ath79/ar933x/lowlevel_init.S new file +7 -0
+LEAF(lowlevel_init)
+   /* These three WLAN_RESET will avoid original issue */
+    li      t3, 0x03
+1:
+    li      t0, KSEG1ADDR(AR71XX_RESET_BASE)
+    lw      t1, AR933X_RESET_REG_RESET_MODULE(t0)
+    ori     t1, t1, 0x0800

arch/mips/mach-ath79/ar933x/lowlevel_init.S line 94

Quoted 10 lines
arch/mips/mach-ath79/ar933x/lowlevel_init.S new file +10 -0
+    sw      t1, AR933X_RESET_REG_RESET_MODULE(t0)
+    nop
+    lw      t1, AR933X_RESET_REG_RESET_MODULE(t0)
+    li      t2, 0xfffff7ff
+    and     t1, t1, t2
+    sw      t1, AR933X_RESET_REG_RESET_MODULE(t0)
+    nop
+    addi    t3, t3, -1
+    bnez    t3, 1b
+     nop

This should be also easy to rewrite into C , right ?

Quoted 7 lines
Quoted 5 lines
Quoted 2 lines

C runtime environment is not available.
C stack is not ready before DDR has initialized.

Just point the stack into a locked cacheline or some onchip RAM and there you have a C runtime. That should be pretty easy :)

How to lock cacheline?

You'd have to check the MIPS core manual, I don't know the details, sorry.

Quoted 2 lines

My guess is that cache memory may be use to map SPI flash at 0x9f000000 by ROM code.

The SPI flash is an IP block which just maps the SPI NOR into the address space, it doesn't use the CPU cache at all.

Maybe you don't even need to lock cachelines though, the AR9331 should have some internal SRAM, so just use that for stack. Do you have a proper datasheet for the Atheros MIPS chips ? I have some 320 pages datasheet for AR9331.

Quoted 19 lines
Quoted 19 lines

[...]

Quoted 17 lines
Quoted 16 lines
Quoted 4 lines
arch/mips/mach-ath79/dram.c new file +4 -0
+phys_size_t initdram(int board_type)
+{
+	uint8_t *addr, *p;
+	int i;

arch/mips/mach-ath79/dram.c line 25

Quoted 10 lines
arch/mips/mach-ath79/dram.c new file +10 -0
+
+	ddr_tap_init();
+	addr = (uint8_t *)KSEG1;
+	*addr = 0x77;
+	for (i = 0, p = addr; p < (uint8_t *)KSEG2; i++) {
+		p += 0x1000000;
+		*p = i;
+		if (*addr != 0x77)
+			break;
+	}

What is this and how does it work ?

Quoted 4 lines
Quoted 4 lines
Quoted 1 line

Physical memory was mapped circularly for this chip.

Can you please expand on that ? I am not as deep in this chip as you are, so please explain it to me in a bit more detail.

Well ... ?

Quoted 16 lines
Quoted 16 lines
Quoted 2 lines
Quoted 2 lines
Quoted 2 lines
arch/mips/mach-ath79/dram.c new file +2 -0
+	return (phys_size_t)(p - addr);
+}

[...]

Quoted 8 lines
Quoted 6 lines

arch/mips/mach-ath79/reset.c line 50

Quoted 4 lines
arch/mips/mach-ath79/reset.c new file +4 -0
+	if (reg) {
+		val = RST_READ(reg);
+		val |= AR71XX_RESET_FULL_CHIP;
+		RST_WRITE(reg, val);

setbits_le32() please.

Macro setbits_le32() is not available for MIPS architecture.

You can always add them :)

Quoted 7 lines
Quoted 5 lines
Quoted 2 lines

Other, I don't think there is better in being so explicit and using little-endian.

I believe your register accesses should have correct endianness exactly beause mips can be both endian.

What is the advantage of using setbits_le32()?

You don't have these constant repeating patterns of:

var = read()
var |= BIT
write(var)

It makes things a bit less confusing.

Best regards,
Marek Vasut

author
#7 lore raw

PATCH v3 1/4 mips: add base support for atheros ath79 based SOCs

Quoted 31 lines · Marek Vasut
Quoted 22 lines · Wills Wang
Quoted 21 lines · Marek Vasut

On Thursday, December 24, 2015 at 02:51:06 PM, Wills Wang wrote:

[...]

Quoted 17 lines
Quoted 17 lines
Quoted 17 lines
arch/mips/mach-ath79/ar933x/lowlevel_init.S new file +17 -0
+LEAF(lowlevel_init)
+   /* These three WLAN_RESET will avoid original issue */
+    li      t3, 0x03
+1:
+    li      t0, KSEG1ADDR(AR71XX_RESET_BASE)
+    lw      t1, AR933X_RESET_REG_RESET_MODULE(t0)
+    ori     t1, t1, 0x0800
+    sw      t1, AR933X_RESET_REG_RESET_MODULE(t0)
+    nop
+    lw      t1, AR933X_RESET_REG_RESET_MODULE(t0)
+    li      t2, 0xfffff7ff
+    and     t1, t1, t2
+    sw      t1, AR933X_RESET_REG_RESET_MODULE(t0)
+    nop
+    addi    t3, t3, -1
+    bnez    t3, 1b
+     nop
Quoted 6 lines
Quoted 5 lines
Quoted 3 lines
Quoted 1 line

This should be also easy to rewrite into C , right ?

C runtime environment is not available.
C stack is not ready before DDR has initialized.

Just point the stack into a locked cacheline or some onchip RAM and there you have a C runtime. That should be pretty easy :)

How to lock cacheline?

You'd have to check the MIPS core manual, I don't know the details, sorry.

Quoted 8 lines
Quoted 2 lines

My guess is that cache memory may be use to map SPI flash at 0x9f000000 by ROM code.

The SPI flash is an IP block which just maps the SPI NOR into the address space, it doesn't use the CPU cache at all.

Maybe you don't even need to lock cachelines though, the AR9331 should have some internal SRAM, so just use that for stack. Do you have a proper datasheet for the Atheros MIPS chips ? I have some 320 pages datasheet for AR9331.

I don't find any description about internal SRAM in public datasheet. About mapping SPI flash, there is a doubt, who fetch the instruction from the SPI Nor flash to CPU pipe line when chip boot from SPI flash? I guess that ROM code handle cache exception and load instruction/date from SPI flash into cache.

Quoted 17 lines
Quoted 17 lines
Quoted 17 lines

[...]

Quoted 15 lines
Quoted 15 lines
Quoted 4 lines
arch/mips/mach-ath79/dram.c new file +4 -0
+phys_size_t initdram(int board_type)
+{
+	uint8_t *addr, *p;
+	int i;

arch/mips/mach-ath79/dram.c line 25

Quoted 10 lines
arch/mips/mach-ath79/dram.c new file +10 -0
+
+	ddr_tap_init();
+	addr = (uint8_t *)KSEG1;
+	*addr = 0x77;
+	for (i = 0, p = addr; p < (uint8_t *)KSEG2; i++) {
+		p += 0x1000000;
+		*p = i;
+		if (*addr != 0x77)
+			break;
+	}

What is this and how does it work ?

Quoted 4 lines
Quoted 3 lines
Quoted 3 lines
Quoted 1 line

Physical memory was mapped circularly for this chip.

Can you please expand on that ? I am not as deep in this chip as you are, so please explain it to me in a bit more detail.

Well ... ?

There is 64MB DDR on my board, the 64MB memory was mapped circularly into 0x00000000-0x03ffffff, 0x04000000-0x07ffffff, 0x08000000-0x0bffffff,... the address 0x00000000, 0x04000000 and 0x08000000 was mapped to the same physical memory. their corresponding KSEG1 address is 0xA0000000, 0xA4000000,
0xA8000000, when write a value into 0xA0000000, we can read the same value from address 0xA4000000 and 0xA8000000.

Quoted 17 lines
Quoted 17 lines
Quoted 17 lines
Quoted 3 lines
Quoted 3 lines
Quoted 3 lines
arch/mips/mach-ath79/dram.c new file +2 -0
+	return (phys_size_t)(p - addr);
+}

[...]

Quoted 6 lines
Quoted 5 lines

arch/mips/mach-ath79/reset.c line 50

Quoted 4 lines
arch/mips/mach-ath79/reset.c new file +4 -0
+	if (reg) {
+		val = RST_READ(reg);
+		val |= AR71XX_RESET_FULL_CHIP;
+		RST_WRITE(reg, val);

setbits_le32() please.

Macro setbits_le32() is not available for MIPS architecture.

You can always add them :)

Quoted 2 lines

Other, I don't think there is better in being so explicit and using little-endian.

I believe your register accesses should have correct endianness exactly beause mips can be both endian.

Quoted 8 lines
Quoted 1 line

What is the advantage of using setbits_le32()?

You don't have these constant repeating patterns of:

var = read()
var |= BIT
write(var)

It makes things a bit less confusing.

ok, AR9331 use big-endian.

Quoted 4 lines

Best regards,
Marek Vasut

#8 lore raw

PATCH v3 1/4 mips: add base support for atheros ath79 based SOCs

On Saturday, December 26, 2015 at 04:48:57 PM, Wills Wang wrote:

[...]

Quoted 8 lines
Quoted 7 lines

The SPI flash is an IP block which just maps the SPI NOR into the address space, it doesn't use the CPU cache at all.

Maybe you don't even need to lock cachelines though, the AR9331 should have some internal SRAM, so just use that for stack. Do you have a proper datasheet for the Atheros MIPS chips ? I have some 320 pages datasheet for AR9331.

Quoted 5 lines

I don't find any description about internal SRAM in public datasheet. About mapping SPI flash, there is a doubt, who fetch the instruction from the SPI Nor flash to CPU pipe line when chip boot from SPI flash? I guess that ROM code handle cache exception and load instruction/date from SPI flash into cache.

I just pulled out the SPI NOR from the Arduino Yun I have here and connected an FPGA with SPI NOR emulator in there. All the chip does is it issues the fastread opcode to the SPI NOR when it boots. It does the same thing if you access the 0x9f000000..0x9fxxxxxx address range from the ancient U-Boot 1.1.x.

My impression is that the SPI NOR controller in the chip does a mapping between the SPI NOR and the memory mapped access to the 0x9fxxxxxx range. There is no caching involved in that, all of this is done internally in the SPI NOR block.

The mips24kc core should support locking cache lines , so if the SRAM is not available, this would have to do.

Quoted 26 lines
Quoted 19 lines
Quoted 19 lines
Quoted 19 lines

[...]

Quoted 17 lines
Quoted 16 lines
Quoted 4 lines
(quoted diff) +4 -0
+phys_size_t initdram(int board_type)
+{
+	uint8_t *addr, *p;
+	int i;

Review

Quoted 10 lines
(quoted diff) +10 -0
+
+	ddr_tap_init();
+	addr = (uint8_t *)KSEG1;
+	*addr = 0x77;
+	for (i = 0, p = addr; p < (uint8_t *)KSEG2; i++) {
+		p += 0x1000000;
+		*p = i;
+		if (*addr != 0x77)
+			break;
+	}

What is this and how does it work ?

Quoted 6 lines
Quoted 4 lines
Quoted 4 lines
Quoted 1 line

Physical memory was mapped circularly for this chip.

Can you please expand on that ? I am not as deep in this chip as you are, so please explain it to me in a bit more detail.

Well ... ?

Quoted 7 lines

There is 64MB DDR on my board, the 64MB memory was mapped circularly into 0x00000000-0x03ffffff, 0x04000000-0x07ffffff, 0x08000000-0x0bffffff,... the address 0x00000000, 0x04000000 and 0x08000000 was mapped to the same physical memory. their corresponding KSEG1 address is 0xA0000000, 0xA4000000,
0xA8000000, when write a value into 0xA0000000, we can read the same value from address 0xA4000000 and 0xA8000000.

So this is some sort of poor man's memory size detection mechanism ?

See common/memsize.c , function get_ram_size() . That might help instead.

Quoted 26 lines
Quoted 26 lines
Quoted 16 lines
Quoted 16 lines
Quoted 2 lines
Quoted 2 lines
Quoted 2 lines
(quoted diff) +2 -0
+	return (phys_size_t)(p - addr);
+}

[...]

Quoted 8 lines
Quoted 6 lines

Review

Quoted 4 lines
(quoted diff) +4 -0
+	if (reg) {
+		val = RST_READ(reg);
+		val |= AR71XX_RESET_FULL_CHIP;
+		RST_WRITE(reg, val);

setbits_le32() please.

Macro setbits_le32() is not available for MIPS architecture.

You can always add them :)

Quoted 7 lines
Quoted 5 lines
Quoted 2 lines

Other, I don't think there is better in being so explicit and using little-endian.

I believe your register accesses should have correct endianness exactly beause mips can be both endian.

What is the advantage of using setbits_le32()?

You don't have these constant repeating patterns of:

Quoted 7 lines
Quoted 5 lines

var = read()
var |= BIT
write(var)

It makes things a bit less confusing.

ok, AR9331 use big-endian.

setbits_be32() then, same thing.

#9 lore raw

PATCH v3 1/4 mips: add base support for atheros ath79 based SOCs

Quoted 24 lines · Marek Vasut

On Saturday, December 26, 2015 at 04:48:57 PM, Wills Wang wrote:

[...]

Quoted 8 lines
Quoted 7 lines

The SPI flash is an IP block which just maps the SPI NOR into the address space, it doesn't use the CPU cache at all.

Maybe you don't even need to lock cachelines though, the AR9331 should have some internal SRAM, so just use that for stack. Do you have a proper datasheet for the Atheros MIPS chips ? I have some 320 pages datasheet for AR9331.

Quoted 5 lines

I don't find any description about internal SRAM in public datasheet. About mapping SPI flash, there is a doubt, who fetch the instruction from the SPI Nor flash to CPU pipe line when chip boot from SPI flash? I guess that ROM code handle cache exception and load instruction/date from SPI flash into cache.

I just pulled out the SPI NOR from the Arduino Yun I have here and connected an FPGA with SPI NOR emulator in there. All the chip does is it issues the fastread opcode to the SPI NOR when it boots. It does the same thing if you access the 0x9f000000..0x9fxxxxxx address range from the ancient U-Boot 1.1.x.

Quoted 7 lines

My impression is that the SPI NOR controller in the chip does a mapping between the SPI NOR and the memory mapped access to the 0x9fxxxxxx range. There is no caching involved in that, all of this is done internally in the SPI NOR block.

The mips24kc core should support locking cache lines , so if the SRAM is not available, this would have to do.

Ha, look at this [1]. risk @ #openwrt-devel at freenode pointed this location out (thanks!)

[1] https://github.com/pepe2k/u-boot_mod/blob/master/u-
boot/cpu/mips/start.S#L652

Best regards,
Marek Vasut

author
#10 lore raw

PATCH v3 1/4 mips: add base support for atheros ath79 based SOCs

WASP is ar9341.

Quoted 40 lines · Marek Vasut
Quoted 22 lines · Marek Vasut

On Saturday, December 26, 2015 at 04:48:57 PM, Wills Wang wrote:

[...]

Quoted 7 lines
Quoted 7 lines

The SPI flash is an IP block which just maps the SPI NOR into the address space, it doesn't use the CPU cache at all.

Maybe you don't even need to lock cachelines though, the AR9331 should have some internal SRAM, so just use that for stack. Do you have a proper datasheet for the Atheros MIPS chips ? I have some 320 pages datasheet for AR9331.

Quoted 5 lines

I don't find any description about internal SRAM in public datasheet. About mapping SPI flash, there is a doubt, who fetch the instruction from the SPI Nor flash to CPU pipe line when chip boot from SPI flash? I guess that ROM code handle cache exception and load instruction/date from SPI flash into cache.

I just pulled out the SPI NOR from the Arduino Yun I have here and connected an FPGA with SPI NOR emulator in there. All the chip does is it issues the fastread opcode to the SPI NOR when it boots. It does the same thing if you access the 0x9f000000..0x9fxxxxxx address range from the ancient U-Boot 1.1.x.

Quoted 7 lines

My impression is that the SPI NOR controller in the chip does a mapping between the SPI NOR and the memory mapped access to the 0x9fxxxxxx range. There is no caching involved in that, all of this is done internally in the SPI NOR block.

The mips24kc core should support locking cache lines , so if the SRAM is not available, this would have to do.

Ha, look at this [1]. risk @ #openwrt-devel at freenode pointed this location out (thanks!)

[1] https://github.com/pepe2k/u-boot_mod/blob/master/u-
boot/cpu/mips/start.S#L652

Best regards,
Marek Vasut

#11 lore raw

PATCH v3 1/4 mips: add base support for atheros ath79 based SOCs

Quoted 1 line · Wills Wang

WASP is ar9341.

Please do not top post.

Did you try if the memory is accessible on your platform ? AR9331 I have here has the SRAM at 0xbd007000 , just like that machine in [1] .

Quoted 34 lines · Marek Vasut
Quoted 33 lines · Marek Vasut
Quoted 31 lines · Wills Wang

[...]

Quoted 8 lines
Quoted 7 lines

The SPI flash is an IP block which just maps the SPI NOR into the address space, it doesn't use the CPU cache at all.

Maybe you don't even need to lock cachelines though, the AR9331 should have some internal SRAM, so just use that for stack. Do you have a proper datasheet for the Atheros MIPS chips ? I have some 320 pages datasheet for AR9331.

Quoted 5 lines

I don't find any description about internal SRAM in public datasheet. About mapping SPI flash, there is a doubt, who fetch the instruction from the SPI Nor flash to CPU pipe line when chip boot from SPI flash? I guess that ROM code handle cache exception and load instruction/date from SPI flash into cache.

I just pulled out the SPI NOR from the Arduino Yun I have here and connected an FPGA with SPI NOR emulator in there. All the chip does is it issues the fastread opcode to the SPI NOR when it boots. It does the same thing if you access the 0x9f000000..0x9fxxxxxx address range from the ancient U-Boot 1.1.x.

My impression is that the SPI NOR controller in the chip does a mapping between the SPI NOR and the memory mapped access to the 0x9fxxxxxx range. There is no caching involved in that, all of this is done internally in the SPI NOR block.

The mips24kc core should support locking cache lines , so if the SRAM is not available, this would have to do.

Quoted 8 lines
Quoted 8 lines

Ha, look at this [1]. risk @ #openwrt-devel at freenode pointed this location out (thanks!)

[1] https://github.com/pepe2k/u-boot_mod/blob/master/u-
boot/cpu/mips/start.S#L652

Best regards,
Marek Vasut

Best regards,
Marek Vasut

author
#12 lore raw

PATCH v3 1/4 mips: add base support for atheros ath79 based SOCs

Quoted 6 lines · Marek Vasut
Quoted 1 line · Wills Wang

WASP is ar9341.

Please do not top post.

Did you try if the memory is accessible on your platform ? AR9331 I have here has the SRAM at 0xbd007000 , just like that machine in [1] .

I found there is a memory segment at 0xbd000000...0xbd007fff. it's independent of DDR physical memory, can be read and wrote, but hardware can't boot up if don't execute lowlevel_init.S when define CONFIG_SYS_INIT_SP_ADDR=0xbd007000 to set C stack into SRAM.

Best Regards
Wills

#13 lore raw

PATCH v3 1/4 mips: add base support for atheros ath79 based SOCs

Quoted 6 lines · Wills Wang
Quoted 5 lines · Marek Vasut
Quoted 1 line · Wills Wang

WASP is ar9341.

Please do not top post.

Quoted 7 lines
Quoted 2 lines

Did you try if the memory is accessible on your platform ? AR9331 I have here has the SRAM at 0xbd007000 , just like that machine in [1] .

I found there is a memory segment at 0xbd000000...0xbd007fff. it's independent of DDR physical memory, can be read and wrote, but hardware can't boot up if don't execute lowlevel_init.S when define CONFIG_SYS_INIT_SP_ADDR=0xbd007000 to set C stack into SRAM.

Stack grows down, so of course if you put stack at the beginning of SRAM, that cannot work ;-) Put it at the end , 0xbd008000.

Best regards,
Marek Vasut

author
#14 lore raw

PATCH v3 1/4 mips: add base support for atheros ath79 based SOCs

Quoted 6 lines · Marek Vasut
Quoted 5 lines · Wills Wang
Quoted 4 lines · Marek Vasut
Quoted 1 line · Wills Wang

WASP is ar9341.

Please do not top post.

Quoted 8 lines
Quoted 6 lines
Quoted 2 lines

Did you try if the memory is accessible on your platform ? AR9331 I have here has the SRAM at 0xbd007000 , just like that machine in [1] .

I found there is a memory segment at 0xbd000000...0xbd007fff. it's independent of DDR physical memory, can be read and wrote, but hardware can't boot up if don't execute lowlevel_init.S when define CONFIG_SYS_INIT_SP_ADDR=0xbd007000 to set C stack into SRAM.

Stack grows down, so of course if you put stack at the beginning of SRAM, that cannot work ;-) Put it at the end , 0xbd008000.

This memory segment was mapped circularly at 0xbd000000...0xbdffffff.

Quoted 4 lines

Best regards,
Marek Vasut

#15 lore raw

PATCH v3 1/4 mips: add base support for atheros ath79 based SOCs

Quoted 16 lines · Wills Wang
Quoted 15 lines · Marek Vasut
Quoted 13 lines · Wills Wang
Quoted 7 lines · Marek Vasut
Quoted 1 line · Wills Wang

WASP is ar9341.

Please do not top post.

Did you try if the memory is accessible on your platform ? AR9331 I have here has the SRAM at 0xbd007000 , just like that machine in [1] .

I found there is a memory segment at 0xbd000000...0xbd007fff. it's independent of DDR physical memory, can be read and wrote, but hardware can't boot up if don't execute lowlevel_init.S when define CONFIG_SYS_INIT_SP_ADDR=0xbd007000 to set C stack into SRAM.

Quoted 4 lines
Quoted 2 lines

Stack grows down, so of course if you put stack at the beginning of SRAM, that cannot work ;-) Put it at the end , 0xbd008000.

This memory segment was mapped circularly at 0xbd000000...0xbdffffff.

So is this area at 0xbd008000 usable for stack or not ?

Best regards,
Marek Vasut

author
#16 lore raw

PATCH v3 1/4 mips: add base support for atheros ath79 based SOCs

Quoted 10 lines · Marek Vasut
Quoted 9 lines · Wills Wang
Quoted 8 lines · Marek Vasut
Quoted 7 lines · Wills Wang
Quoted 6 lines · Marek Vasut
Quoted 1 line · Wills Wang

WASP is ar9341.

Please do not top post.

Did you try if the memory is accessible on your platform ? AR9331 I have here has the SRAM at 0xbd007000 , just like that machine in [1] .

Quoted 8 lines
Quoted 7 lines
Quoted 6 lines
Quoted 4 lines

I found there is a memory segment at 0xbd000000...0xbd007fff. it's independent of DDR physical memory, can be read and wrote, but hardware can't boot up if don't execute lowlevel_init.S when define CONFIG_SYS_INIT_SP_ADDR=0xbd007000 to set C stack into SRAM.

Stack grows down, so of course if you put stack at the beginning of SRAM, that cannot work ;-) Put it at the end , 0xbd008000.

This memory segment was mapped circularly at 0xbd000000...0xbdffffff.

So is this area at 0xbd008000 usable for stack or not ?

Same times board can boot up, but in a very unstable. i use the following setting:

#define CONFIG_SYS_INIT_RAM_ADDR 0xbd000000
#define CONFIG_SYS_INIT_RAM_SIZE (32 * SZ_1K)

#define CONFIG_SYS_INIT_SP_OFFSET \
(CONFIG_SYS_INIT_RAM_SIZE - GENERATED_GBL_DATA_SIZE)
#define CONFIG_SYS_INIT_SP_ADDR \
(CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_INIT_SP_OFFSET)

Quoted 4 lines

Best regards,
Marek Vasut

Signature · 2 lines
Best Regards
Wills
#17 lore raw

PATCH v3 1/4 mips: add base support for atheros ath79 based SOCs

Quoted 22 lines · Wills Wang
Quoted 21 lines · Marek Vasut
Quoted 20 lines · Wills Wang
Quoted 18 lines · Marek Vasut
Quoted 6 lines · Wills Wang
Quoted 5 lines · Marek Vasut
Quoted 1 line · Wills Wang

WASP is ar9341.

Please do not top post.

Quoted 8 lines
Quoted 3 lines

Did you try if the memory is accessible on your platform ? AR9331 I have here has the SRAM at 0xbd007000 , just like that machine in [1] .

I found there is a memory segment at 0xbd000000...0xbd007fff. it's independent of DDR physical memory, can be read and wrote, but hardware can't boot up if don't execute lowlevel_init.S when define CONFIG_SYS_INIT_SP_ADDR=0xbd007000 to set C stack into SRAM.

Stack grows down, so of course if you put stack at the beginning of SRAM, that cannot work ;-) Put it at the end , 0xbd008000.

Quoted 8 lines
Quoted 3 lines
Quoted 1 line

This memory segment was mapped circularly at 0xbd000000...0xbdffffff.

So is this area at 0xbd008000 usable for stack or not ?

Same times board can boot up, but in a very unstable. i use the following setting:

#define CONFIG_SYS_INIT_RAM_ADDR 0xbd000000

Should be 0xbd007000

Quoted 1 line

#define CONFIG_SYS_INIT_RAM_SIZE (32 * SZ_1K)

Should be 4 KiB large.

Quoted 4 lines

#define CONFIG_SYS_INIT_SP_OFFSET \
(CONFIG_SYS_INIT_RAM_SIZE - GENERATED_GBL_DATA_SIZE)
#define CONFIG_SYS_INIT_SP_ADDR \
(CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_INIT_SP_OFFSET)

Did you investigate why the board has problems ?

Best regards,
Marek Vasut

author
#18 lore raw

PATCH v3 1/4 mips: add base support for atheros ath79 based SOCs

Quoted 27 lines · Marek Vasut
Quoted 16 lines · Wills Wang
Quoted 15 lines · Marek Vasut
Quoted 14 lines · Wills Wang
Quoted 13 lines · Marek Vasut
Quoted 12 lines · Wills Wang
Quoted 7 lines · Marek Vasut
Quoted 1 line · Wills Wang

WASP is ar9341.

Please do not top post.

Did you try if the memory is accessible on your platform ? AR9331 I have here has the SRAM at 0xbd007000 , just like that machine in [1] .

I found there is a memory segment at 0xbd000000...0xbd007fff. it's independent of DDR physical memory, can be read and wrote, but hardware can't boot up if don't execute lowlevel_init.S when define CONFIG_SYS_INIT_SP_ADDR=0xbd007000 to set C stack into SRAM.

Quoted 8 lines
Quoted 4 lines
Quoted 3 lines
Quoted 2 lines

Stack grows down, so of course if you put stack at the beginning of SRAM, that cannot work ;-) Put it at the end , 0xbd008000.

This memory segment was mapped circularly at 0xbd000000...0xbdffffff.

So is this area at 0xbd008000 usable for stack or not ?

Same times board can boot up, but in a very unstable. i use the following setting:

#define CONFIG_SYS_INIT_RAM_ADDR 0xbd000000

Should be 0xbd007000

Quoted 8 lines
Quoted 1 line

#define CONFIG_SYS_INIT_RAM_SIZE (32 * SZ_1K)

Should be 4 KiB large.

Quoted 4 lines

#define CONFIG_SYS_INIT_SP_OFFSET \
(CONFIG_SYS_INIT_RAM_SIZE - GENERATED_GBL_DATA_SIZE)
#define CONFIG_SYS_INIT_SP_ADDR \
(CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_INIT_SP_OFFSET)

Did you investigate why the board has problems ?

"lowlevel_init.S" can't be dropped.

Quoted 5 lines

Best regards,
Marek Vasut

Signature · 2 lines
Best Regards
Wills
#19 lore raw

PATCH v3 1/4 mips: add base support for atheros ath79 based SOCs

Quoted 43 lines · Wills Wang
Quoted 42 lines · Marek Vasut
Quoted 22 lines · Wills Wang
Quoted 21 lines · Marek Vasut
Quoted 20 lines · Wills Wang
Quoted 18 lines · Marek Vasut
Quoted 6 lines · Wills Wang
Quoted 5 lines · Marek Vasut
Quoted 1 line · Wills Wang

WASP is ar9341.

Please do not top post.

Quoted 8 lines
Quoted 3 lines

Did you try if the memory is accessible on your platform ? AR9331 I have here has the SRAM at 0xbd007000 , just like that machine in
[1] .

I found there is a memory segment at 0xbd000000...0xbd007fff. it's independent of DDR physical memory, can be read and wrote, but hardware can't boot up if don't execute lowlevel_init.S when define CONFIG_SYS_INIT_SP_ADDR=0xbd007000 to set C stack into SRAM.

Stack grows down, so of course if you put stack at the beginning of SRAM, that cannot work ;-) Put it at the end , 0xbd008000.

Quoted 8 lines
Quoted 3 lines
Quoted 1 line

This memory segment was mapped circularly at 0xbd000000...0xbdffffff.

So is this area at 0xbd008000 usable for stack or not ?

Same times board can boot up, but in a very unstable. i use the following setting:

#define CONFIG_SYS_INIT_RAM_ADDR 0xbd000000

Should be 0xbd007000

Quoted 1 line

#define CONFIG_SYS_INIT_RAM_SIZE (32 * SZ_1K)

Should be 4 KiB large.

Quoted 4 lines

#define CONFIG_SYS_INIT_SP_OFFSET \

(CONFIG_SYS_INIT_RAM_SIZE - GENERATED_GBL_DATA_SIZE)

Quoted 7 lines
Quoted 5 lines
Quoted 3 lines

#define CONFIG_SYS_INIT_SP_ADDR \

(CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_INIT_SP_OFFSET)

Did you investigate why the board has problems ?

"lowlevel_init.S" can't be dropped.

Thank you very much for all the effort you put into investigating and explaining why this SRAM area cannot be used ... not. From my side, consider this patch to be NAKed.

Best regards,
Marek Vasut

author
#20 lore raw

PATCH v3 1/4 mips: add base support for atheros ath79 based SOCs

Quoted 39 lines · Marek Vasut
Quoted 38 lines · Wills Wang
Quoted 37 lines · Marek Vasut
Quoted 16 lines · Wills Wang
Quoted 15 lines · Marek Vasut
Quoted 14 lines · Wills Wang
Quoted 13 lines · Marek Vasut
Quoted 12 lines · Wills Wang
Quoted 7 lines · Marek Vasut
Quoted 1 line · Wills Wang

WASP is ar9341.

Please do not top post.

Did you try if the memory is accessible on your platform ? AR9331 I have here has the SRAM at 0xbd007000 , just like that machine in
[1] .

I found there is a memory segment at 0xbd000000...0xbd007fff. it's independent of DDR physical memory, can be read and wrote, but hardware can't boot up if don't execute lowlevel_init.S when define CONFIG_SYS_INIT_SP_ADDR=0xbd007000 to set C stack into SRAM.

Quoted 8 lines
Quoted 4 lines
Quoted 3 lines
Quoted 2 lines

Stack grows down, so of course if you put stack at the beginning of SRAM, that cannot work ;-) Put it at the end , 0xbd008000.

This memory segment was mapped circularly at 0xbd000000...0xbdffffff.

So is this area at 0xbd008000 usable for stack or not ?

Same times board can boot up, but in a very unstable. i use the following setting:

#define CONFIG_SYS_INIT_RAM_ADDR 0xbd000000

Should be 0xbd007000

Quoted 1 line

#define CONFIG_SYS_INIT_RAM_SIZE (32 * SZ_1K)

Should be 4 KiB large.

Quoted 7 lines

#define CONFIG_SYS_INIT_SP_OFFSET \

(CONFIG_SYS_INIT_RAM_SIZE - GENERATED_GBL_DATA_SIZE)

#define CONFIG_SYS_INIT_SP_ADDR \

(CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_INIT_SP_OFFSET)

Quoted 10 lines
Quoted 2 lines
Quoted 1 line

Did you investigate why the board has problems ?

"lowlevel_init.S" can't be dropped.

Thank you very much for all the effort you put into investigating and explaining why this SRAM area cannot be used ... not. From my side, consider this patch to be NAKed.

Best regards,
Marek Vasut

"lowlevel_init.S" can't be entirely dropped, there are three main reasons for this.
1. Chip has an original issue, need reset "WLAN" three times to avoid it when power up.
2. Need reset RTC and force to wake MAC, or chip can't work .
3. Need initialise PLL clock for CPU/DDR/AHB, the default clock is 25MHz, the interval from
power-up to printout is about 5s.
So, assembler code could not be avoided even using SRAM for c stack. Now that chipmaker don't open SRAM of this chip and recommend DDR for initial stack, i think
that using DDR should be more consolidated.

Signature · 2 lines
Best Regards
Wills
#21 lore raw

PATCH v3 1/4 mips: add base support for atheros ath79 based SOCs

On Monday, December 28, 2015 at 12:17:41 PM, Wills Wang wrote:
[...]

Quoted 11 lines
Quoted 8 lines
Quoted 1 line

"lowlevel_init.S" can't be dropped.

Thank you very much for all the effort you put into investigating and explaining why this SRAM area cannot be used ... not. From my side, consider this patch to be NAKed.

Best regards,
Marek Vasut

"lowlevel_init.S" can't be entirely dropped, there are three main reasons for this.

Right, so I checked how these are performed and whether these can or cannot be done from C code.

Quoted 2 lines

1. Chip has an original issue, need reset "WLAN" three times to avoid it when power up.

26 /* These three wlan reset will avoid original issue, 27 so full chip reset isn't needed here. */

 28     set_reg(0xb806001c, 0x00c06b30)
 29     nop
 30     set_reg(0xb806001c, 0x00c06330)
 31     nop
 32     set_reg(0xb806001c, 0x00c06b30)
 33     nop
 34     set_reg(0xb806001c, 0x00c06330)
 35     nop
 36 reset_wlan:
 37     set_reg(0xb806001c, 0x00c06b30)
 38     nop
 39     set_reg(0xb806001c, 0x00c06330)
 40     nop

Yes, these can be done from C code.

Quoted 1 line

2. Need reset RTC and force to wake MAC, or chip can't work .

73 /* RTC reset */

 74     set_reg(0x1810704c, 0x00000003)
 75     nop
 76     nop
 77     set_reg(0x18107040, 0x00000000)
 78     nop
 79     nop
 80     set_reg(0x18107040, 0x00000001)
 81     nop

DTTO.

Quoted 3 lines

3. Need initialise PLL clock for CPU/DDR/AHB, the default clock is 25MHz, the interval from
power-up to printout is about 5s.

The PLL configuration is again a set of writes to some random registers. This can again be done from the C code.

Quoted 1 line

So, assembler code could not be avoided even using SRAM for c stack.

I am not convinced, see above. Please show me where exactly is the assembly code imperative. I simply do not see it.

Quoted 3 lines

Now that chipmaker don't open SRAM of this chip and recommend DDR for initial stack, i think
that using DDR should be more consolidated.

I do not care what the chip maker says unless there is an explicit explanation why they require that. Most often, these sorts of "limitations" are in place only because the chipmaker has incompetent software engineers.

So I would like to see either the SRAM or locked cacheline used for stack and then lowlevel init converted into proper C code unless there is an explicit explanation why this can not be done. And by explicit I mean for example a snippet of code which cannot be converted into C code. Note that asm volatile can still be used to contain such small bits of assembler code if needed be.

Best regards,
Marek Vasut

author
#22 lore raw

PATCH v3 1/4 mips: add base support for atheros ath79 based SOCs

Quoted 64 lines · Marek Vasut

On Monday, December 28, 2015 at 12:17:41 PM, Wills Wang wrote:
[...]

Quoted 9 lines
Quoted 7 lines
Quoted 1 line

"lowlevel_init.S" can't be dropped.

Thank you very much for all the effort you put into investigating and explaining why this SRAM area cannot be used ... not. From my side, consider this patch to be NAKed.

Best regards,
Marek Vasut

"lowlevel_init.S" can't be entirely dropped, there are three main reasons for this.

Right, so I checked how these are performed and whether these can or cannot be done from C code.

Quoted 2 lines

1. Chip has an original issue, need reset "WLAN" three times to avoid it when power up.

26 /* These three wlan reset will avoid original issue, 27 so full chip reset isn't needed here. */

  28     set_reg(0xb806001c, 0x00c06b30)
  29     nop
  30     set_reg(0xb806001c, 0x00c06330)
  31     nop
  32     set_reg(0xb806001c, 0x00c06b30)
  33     nop
  34     set_reg(0xb806001c, 0x00c06330)
  35     nop
  36 reset_wlan:
  37     set_reg(0xb806001c, 0x00c06b30)
  38     nop
  39     set_reg(0xb806001c, 0x00c06330)
  40     nop

Yes, these can be done from C code.

Quoted 1 line

2. Need reset RTC and force to wake MAC, or chip can't work .

73 /* RTC reset */

  74     set_reg(0x1810704c, 0x00000003)
  75     nop
  76     nop
  77     set_reg(0x18107040, 0x00000000)
  78     nop
  79     nop
  80     set_reg(0x18107040, 0x00000001)
  81     nop

DTTO.

Quoted 3 lines

3. Need initialise PLL clock for CPU/DDR/AHB, the default clock is 25MHz, the interval from
power-up to printout is about 5s.

The PLL configuration is again a set of writes to some random registers. This can again be done from the C code.

Quoted 1 line

So, assembler code could not be avoided even using SRAM for c stack.

I am not convinced, see above. Please show me where exactly is the assembly code imperative. I simply do not see it.

Quoted 3 lines

Now that chipmaker don't open SRAM of this chip and recommend DDR for initial stack, i think
that using DDR should be more consolidated.

I do not care what the chip maker says unless there is an explicit explanation why they require that. Most often, these sorts of "limitations" are in place only because the chipmaker has incompetent software engineers.

Quoted 10 lines

So I would like to see either the SRAM or locked cacheline used for stack and then lowlevel init converted into proper C code unless there is an explicit explanation why this can not be done. And by explicit I mean for example a snippet of code which cannot be converted into C code. Note that asm volatile can still be used to contain such small bits of assembler code if needed be.

Best regards,
Marek Vasut

I made a series of tries in this, and i can confirm that the SRAM can be used for c stack, but the prerequisites for this are that the above two points (1&2) must be execute in lowlevel_init. i has converted these code to C, and put them(1&2) at arch_cpu_init, but hardware don't work, i guess that
these parts may be associated with memory submodule of this chip.

Signature · 2 lines
Best Regards
Wills
author
#23 lore raw

PATCH v3 1/4 mips: add base support for atheros ath79 based SOCs

In reply to Marek Vasut
Quoted 64 lines · Marek Vasut

On Monday, December 28, 2015 at 12:17:41 PM, Wills Wang wrote:
[...]

Quoted 9 lines
Quoted 7 lines
Quoted 1 line

"lowlevel_init.S" can't be dropped.

Thank you very much for all the effort you put into investigating and explaining why this SRAM area cannot be used ... not. From my side, consider this patch to be NAKed.

Best regards,
Marek Vasut

"lowlevel_init.S" can't be entirely dropped, there are three main reasons for this.

Right, so I checked how these are performed and whether these can or cannot be done from C code.

Quoted 2 lines

1. Chip has an original issue, need reset "WLAN" three times to avoid it when power up.

26 /* These three wlan reset will avoid original issue, 27 so full chip reset isn't needed here. */

  28     set_reg(0xb806001c, 0x00c06b30)
  29     nop
  30     set_reg(0xb806001c, 0x00c06330)
  31     nop
  32     set_reg(0xb806001c, 0x00c06b30)
  33     nop
  34     set_reg(0xb806001c, 0x00c06330)
  35     nop
  36 reset_wlan:
  37     set_reg(0xb806001c, 0x00c06b30)
  38     nop
  39     set_reg(0xb806001c, 0x00c06330)
  40     nop

Yes, these can be done from C code.

Quoted 1 line

2. Need reset RTC and force to wake MAC, or chip can't work .

73 /* RTC reset */

  74     set_reg(0x1810704c, 0x00000003)
  75     nop
  76     nop
  77     set_reg(0x18107040, 0x00000000)
  78     nop
  79     nop
  80     set_reg(0x18107040, 0x00000001)
  81     nop

DTTO.

Quoted 3 lines

3. Need initialise PLL clock for CPU/DDR/AHB, the default clock is 25MHz, the interval from
power-up to printout is about 5s.

The PLL configuration is again a set of writes to some random registers. This can again be done from the C code.

Quoted 1 line

So, assembler code could not be avoided even using SRAM for c stack.

I am not convinced, see above. Please show me where exactly is the assembly code imperative. I simply do not see it.

Quoted 3 lines

Now that chipmaker don't open SRAM of this chip and recommend DDR for initial stack, i think
that using DDR should be more consolidated.

I do not care what the chip maker says unless there is an explicit explanation why they require that. Most often, these sorts of "limitations" are in place only because the chipmaker has incompetent software engineers.

Quoted 10 lines

So I would like to see either the SRAM or locked cacheline used for stack and then lowlevel init converted into proper C code unless there is an explicit explanation why this can not be done. And by explicit I mean for example a snippet of code which cannot be converted into C code. Note that asm volatile can still be used to contain such small bits of assembler code if needed be.

Best regards,
Marek Vasut

I made a series of tries in this, i configure initial stack in SRAM and convert
these code to c, and put them in arch_cpu_init(the first available c entry), but
hardware don't work. if i keep the above three points(RESET/RTC/PLL) in lowlevel_init, put other code in arch_cpu_init, board work fine.

Signature · 2 lines
Best Regards
Wills
#24 lore raw

PATCH v3 1/4 mips: add base support for atheros ath79 based SOCs

Quoted 85 lines · Wills Wang
Quoted 81 lines · Marek Vasut

On Monday, December 28, 2015 at 12:17:41 PM, Wills Wang wrote:
[...]

Quoted 11 lines
Quoted 8 lines
Quoted 1 line

"lowlevel_init.S" can't be dropped.

Thank you very much for all the effort you put into investigating and explaining why this SRAM area cannot be used ... not. From my side, consider this patch to be NAKed.

Best regards,
Marek Vasut

"lowlevel_init.S" can't be entirely dropped, there are three main reasons for this.

Right, so I checked how these are performed and whether these can or cannot be done from C code.

Quoted 3 lines

1. Chip has an original issue, need reset "WLAN" three times to avoid it when power up.

26 /* These three wlan reset will avoid original issue, 27 so full chip reset isn't needed here. */

  28     set_reg(0xb806001c, 0x00c06b30)
  29     nop
  30     set_reg(0xb806001c, 0x00c06330)
  31     nop
  32     set_reg(0xb806001c, 0x00c06b30)
  33     nop
  34     set_reg(0xb806001c, 0x00c06330)
  35     nop
  36 reset_wlan:
  37     set_reg(0xb806001c, 0x00c06b30)
  38     nop
  39     set_reg(0xb806001c, 0x00c06330)
  40     nop

Yes, these can be done from C code.

Quoted 2 lines

2. Need reset RTC and force to wake MAC, or chip can't work .

73 /* RTC reset */

  74     set_reg(0x1810704c, 0x00000003)
  75     nop
  76     nop
  77     set_reg(0x18107040, 0x00000000)
  78     nop
  79     nop
  80     set_reg(0x18107040, 0x00000001)
  81     nop

DTTO.

Quoted 3 lines

3. Need initialise PLL clock for CPU/DDR/AHB, the default clock is 25MHz, the interval from
power-up to printout is about 5s.

The PLL configuration is again a set of writes to some random registers. This can again be done from the C code.

Quoted 1 line

So, assembler code could not be avoided even using SRAM for c stack.

I am not convinced, see above. Please show me where exactly is the assembly code imperative. I simply do not see it.

Quoted 3 lines

Now that chipmaker don't open SRAM of this chip and recommend DDR for initial stack, i think
that using DDR should be more consolidated.

I do not care what the chip maker says unless there is an explicit explanation why they require that. Most often, these sorts of "limitations" are in place only because the chipmaker has incompetent software engineers.

So I would like to see either the SRAM or locked cacheline used for stack and then lowlevel init converted into proper C code unless there is an explicit explanation why this can not be done. And by explicit I mean for example a snippet of code which cannot be converted into C code. Note that asm volatile can still be used to contain such small bits of assembler code if needed be.

Quoted 2 lines

Best regards,
Marek Vasut

Quoted 6 lines

I made a series of tries in this, i configure initial stack in SRAM and convert
these code to c, and put them in arch_cpu_init(the first available c entry), but
hardware don't work. if i keep the above three points(RESET/RTC/PLL) in lowlevel_init, put other code in arch_cpu_init, board work fine.

So let me ask the question again -- why does the C code not work ? Did you investigate the reason why does the C code not work ?

Can you share the change you did to convert things to C code ? There might be a bug in that too ...

#25 lore raw

PATCH v3 1/4 mips: add base support for atheros ath79 based SOCs

Am 28.12.2015 um 16:52 schrieb Marek Vasut:

Quoted 93 lines · Wills Wang
Quoted 85 lines · Marek Vasut
Quoted 81 lines · Wills Wang

[...]

Quoted 11 lines
Quoted 8 lines
Quoted 1 line

"lowlevel_init.S" can't be dropped.

Thank you very much for all the effort you put into investigating and explaining why this SRAM area cannot be used ... not. From my side, consider this patch to be NAKed.

Best regards,
Marek Vasut

"lowlevel_init.S" can't be entirely dropped, there are three main reasons for this.

Right, so I checked how these are performed and whether these can or cannot be done from C code.

Quoted 3 lines

1. Chip has an original issue, need reset "WLAN" three times to avoid it when power up.

26 /* These three wlan reset will avoid original issue, 27 so full chip reset isn't needed here. */

  28     set_reg(0xb806001c, 0x00c06b30)
  29     nop
  30     set_reg(0xb806001c, 0x00c06330)
  31     nop
  32     set_reg(0xb806001c, 0x00c06b30)
  33     nop
  34     set_reg(0xb806001c, 0x00c06330)
  35     nop
  36 reset_wlan:
  37     set_reg(0xb806001c, 0x00c06b30)
  38     nop
  39     set_reg(0xb806001c, 0x00c06330)
  40     nop

Yes, these can be done from C code.

Quoted 2 lines

2. Need reset RTC and force to wake MAC, or chip can't work .

73 /* RTC reset */

  74     set_reg(0x1810704c, 0x00000003)
  75     nop
  76     nop
  77     set_reg(0x18107040, 0x00000000)
  78     nop
  79     nop
  80     set_reg(0x18107040, 0x00000001)
  81     nop

DTTO.

Quoted 3 lines

3. Need initialise PLL clock for CPU/DDR/AHB, the default clock is 25MHz, the interval from
power-up to printout is about 5s.

The PLL configuration is again a set of writes to some random registers. This can again be done from the C code.

Quoted 1 line

So, assembler code could not be avoided even using SRAM for c stack.

I am not convinced, see above. Please show me where exactly is the assembly code imperative. I simply do not see it.

Quoted 3 lines

Now that chipmaker don't open SRAM of this chip and recommend DDR for initial stack, i think
that using DDR should be more consolidated.

I do not care what the chip maker says unless there is an explicit explanation why they require that. Most often, these sorts of "limitations" are in place only because the chipmaker has incompetent software engineers.

So I would like to see either the SRAM or locked cacheline used for stack and then lowlevel init converted into proper C code unless there is an explicit explanation why this can not be done. And by explicit I mean for example a snippet of code which cannot be converted into C code. Note that asm volatile can still be used to contain such small bits of assembler code if needed be.

Quoted 2 lines

Best regards,
Marek Vasut

Quoted 6 lines

I made a series of tries in this, i configure initial stack in SRAM and convert
these code to c, and put them in arch_cpu_init(the first available c entry), but
hardware don't work. if i keep the above three points(RESET/RTC/PLL) in lowlevel_init, put other code in arch_cpu_init, board work fine.

Quoted 6 lines

So let me ask the question again -- why does the C code not work ? Did you investigate the reason why does the C code not work ?

Can you share the change you did to convert things to C code ? There might be a bug in that too ...

it is not a matter of C or assembly, but of the init sequence currently implemented on MIPS. The main purpose of lowlevel_init() is to initialize memory controllers and DRAM. This has to be done in assembly because we have no C runtime environment available at that point.

Also compiling U-Boot as PIC requires to enable MIPS ABI function calls in gcc (-mabicalls). This always creates function prologues and epilogues which are utilizing the stack pointer. Thus we cannot simply convert all lowlevel_init functions to C.

Moving code from lowlevel_init to arch_cpu_init or elsewhere will not work because that code runs too late then. Simply moving the stack to SRAM will also not help because lowlevel_init runs before the stack is available.

Before Wills can convert his code to C, we need to rework the init sequence in start.S. But that is out of the scope of this patch series. I will try to prepare some patches in the next days. The SRAM part should be easy. But the cache line lock need some more work and testing.

In the meantime Wills could send a new patch series, which addresses all other issues except lowlevel_init. The function ddr_tap_init can be already converted to C because it is called from init_dram where a C runtime environment is available. So we could have at least a working patch series and could finalize the review of the other patches. After I have updated u-boot-mips/next branch, Wills can rebase and convert lowlevel_init to C.

Signature · 1 line
- Daniel
#26 lore raw

PATCH v3 1/4 mips: add base support for atheros ath79 based SOCs

Quoted 97 lines · Daniel Schwierzeck

Am 28.12.2015 um 16:52 schrieb Marek Vasut:

Quoted 96 lines · Wills Wang
Quoted 85 lines · Marek Vasut
Quoted 81 lines · Wills Wang

[...]

Quoted 11 lines
Quoted 8 lines
Quoted 1 line

"lowlevel_init.S" can't be dropped.

Thank you very much for all the effort you put into investigating and explaining why this SRAM area cannot be used ... not. From my side, consider this patch to be NAKed.

Best regards,
Marek Vasut

"lowlevel_init.S" can't be entirely dropped, there are three main reasons for this.

Right, so I checked how these are performed and whether these can or cannot be done from C code.

Quoted 3 lines

1. Chip has an original issue, need reset "WLAN" three times to avoid it when power up.

26 /* These three wlan reset will avoid original issue, 27 so full chip reset isn't needed here. */

  28     set_reg(0xb806001c, 0x00c06b30)
  29     nop
  30     set_reg(0xb806001c, 0x00c06330)
  31     nop
  32     set_reg(0xb806001c, 0x00c06b30)
  33     nop
  34     set_reg(0xb806001c, 0x00c06330)
  35     nop
  36 reset_wlan:
  37     set_reg(0xb806001c, 0x00c06b30)
  38     nop
  39     set_reg(0xb806001c, 0x00c06330)
  40     nop

Yes, these can be done from C code.

Quoted 2 lines

2. Need reset RTC and force to wake MAC, or chip can't work .

73 /* RTC reset */

  74     set_reg(0x1810704c, 0x00000003)
  75     nop
  76     nop
  77     set_reg(0x18107040, 0x00000000)
  78     nop
  79     nop
  80     set_reg(0x18107040, 0x00000001)
  81     nop

DTTO.

Quoted 3 lines

3. Need initialise PLL clock for CPU/DDR/AHB, the default clock is 25MHz, the interval from
power-up to printout is about 5s.

The PLL configuration is again a set of writes to some random registers. This can again be done from the C code.

Quoted 1 line

So, assembler code could not be avoided even using SRAM for c stack.

I am not convinced, see above. Please show me where exactly is the assembly code imperative. I simply do not see it.

Quoted 3 lines

Now that chipmaker don't open SRAM of this chip and recommend DDR for initial stack, i think
that using DDR should be more consolidated.

I do not care what the chip maker says unless there is an explicit explanation why they require that. Most often, these sorts of "limitations" are in place only because the chipmaker has incompetent software engineers.

So I would like to see either the SRAM or locked cacheline used for stack and then lowlevel init converted into proper C code unless there is an explicit explanation why this can not be done. And by explicit I mean for example a snippet of code which cannot be converted into C code. Note that asm volatile can still be used to contain such small bits of assembler code if needed be.

Quoted 2 lines

Best regards,
Marek Vasut

Quoted 6 lines

I made a series of tries in this, i configure initial stack in SRAM and convert
these code to c, and put them in arch_cpu_init(the first available c entry), but
hardware don't work. if i keep the above three points(RESET/RTC/PLL) in lowlevel_init, put other code in arch_cpu_init, board work fine.

So let me ask the question again -- why does the C code not work ? Did you investigate the reason why does the C code not work ?

Quoted 7 lines
Quoted 2 lines

Can you share the change you did to convert things to C code ? There might be a bug in that too ...

it is not a matter of C or assembly, but of the init sequence currently implemented on MIPS. The main purpose of lowlevel_init() is to initialize memory controllers and DRAM. This has to be done in assembly because we have no C runtime environment available at that point.

We do this in C on ARM, so I see no problem with this.

Quoted 4 lines

Also compiling U-Boot as PIC requires to enable MIPS ABI function calls in gcc (-mabicalls). This always creates function prologues and epilogues which are utilizing the stack pointer. Thus we cannot simply convert all lowlevel_init functions to C.

I am not saying all, but a list of register writes should be easy to convert.

Quoted 4 lines

Moving code from lowlevel_init to arch_cpu_init or elsewhere will not work because that code runs too late then. Simply moving the stack to SRAM will also not help because lowlevel_init runs before the stack is available.

We have SRAM to place stack in, so stack is available.

Quoted 12 lines

Before Wills can convert his code to C, we need to rework the init sequence in start.S. But that is out of the scope of this patch series. I will try to prepare some patches in the next days. The SRAM part should be easy. But the cache line lock need some more work and testing.

In the meantime Wills could send a new patch series, which addresses all other issues except lowlevel_init. The function ddr_tap_init can be already converted to C because it is called from init_dram where a C runtime environment is available. So we could have at least a working patch series and could finalize the review of the other patches. After I have updated u-boot-mips/next branch, Wills can rebase and convert lowlevel_init to C.

#27 lore raw

PATCH v3 1/4 mips: add base support for atheros ath79 based SOCs

In reply to Marek Vasut

Am 27.12.2015 um 12:04 schrieb Marek Vasut:

Quoted 36 lines · Wills Wang
Quoted 22 lines · Marek Vasut
Quoted 21 lines · Wills Wang
Quoted 20 lines · Marek Vasut
Quoted 18 lines · Wills Wang
Quoted 6 lines · Marek Vasut
Quoted 5 lines · Wills Wang
Quoted 1 line

WASP is ar9341.

Please do not top post.

Quoted 8 lines
Quoted 3 lines

Did you try if the memory is accessible on your platform ? AR9331 I have here has the SRAM at 0xbd007000 , just like that machine in [1] .

I found there is a memory segment at 0xbd000000...0xbd007fff. it's independent of DDR physical memory, can be read and wrote, but hardware can't boot up if don't execute lowlevel_init.S when define CONFIG_SYS_INIT_SP_ADDR=0xbd007000 to set C stack into SRAM.

Stack grows down, so of course if you put stack at the beginning of SRAM, that cannot work ;-) Put it at the end , 0xbd008000.

Quoted 8 lines
Quoted 3 lines
Quoted 1 line

This memory segment was mapped circularly at 0xbd000000...0xbdffffff.

So is this area at 0xbd008000 usable for stack or not ?

Same times board can boot up, but in a very unstable. i use the following setting:

#define CONFIG_SYS_INIT_RAM_ADDR 0xbd000000

Should be 0xbd007000

Quoted 1 line

#define CONFIG_SYS_INIT_RAM_SIZE (32 * SZ_1K)

Quoted 9 lines

Should be 4 KiB large.

Quoted 4 lines

#define CONFIG_SYS_INIT_SP_OFFSET \
(CONFIG_SYS_INIT_RAM_SIZE - GENERATED_GBL_DATA_SIZE)
#define CONFIG_SYS_INIT_SP_ADDR \
(CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_INIT_SP_OFFSET)

Did you investigate why the board has problems ?

according to the description above by Wills those three defines setup the values correctly for start.S:

#define CONFIG_SYS_INIT_RAM_ADDR 0xbd000000
#define CONFIG_SYS_INIT_RAM_SIZE (32 * SZ_1K)
#define CONFIG_SYS_INIT_SP_ADDR \
(CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_INIT_RAM_SIZE)

The stack pointer will then be set to the end of the SRAM area with a 16 Byte alignment. The resulting address should be 0xbd007ff0. From this address, the size of gd_t and CONFIG_SYS_MALLOC_F_LEN will be subtracted. The remaining space is available for the initial stack.

Which value did you chose for CONFIG_SYS_MALLOC_F_LEN? It must be big enough to satisfy all malloc requests by the DM stack and small enough to fit in 32k minus stack size and gd_t size.

Important note: do net set CONFIG_SKIP_LOWLEVEL_INIT yet because that leaves you without initialized RAM or caches. If the setup does not work yet, you likely need to init some extra bits to make the SRAM working.

Signature · 1 line
- Daniel
#28 lore raw

PATCH v3 1/4 mips: add base support for atheros ath79 based SOCs

Quoted 57 lines · Daniel Schwierzeck

Am 27.12.2015 um 12:04 schrieb Marek Vasut:

Quoted 40 lines · Wills Wang
Quoted 22 lines · Marek Vasut
Quoted 21 lines · Wills Wang
Quoted 20 lines · Marek Vasut
Quoted 18 lines · Wills Wang
Quoted 6 lines · Marek Vasut
Quoted 5 lines · Wills Wang
Quoted 1 line

WASP is ar9341.

Please do not top post.

Quoted 8 lines
Quoted 3 lines

Did you try if the memory is accessible on your platform ? AR9331 I have here has the SRAM at 0xbd007000 , just like that machine in
[1] .

I found there is a memory segment at 0xbd000000...0xbd007fff. it's independent of DDR physical memory, can be read and wrote, but hardware can't boot up if don't execute lowlevel_init.S when define CONFIG_SYS_INIT_SP_ADDR=0xbd007000 to set C stack into SRAM.

Stack grows down, so of course if you put stack at the beginning of SRAM, that cannot work ;-) Put it at the end , 0xbd008000.

Quoted 8 lines
Quoted 3 lines
Quoted 1 line

This memory segment was mapped circularly at 0xbd000000...0xbdffffff.

So is this area at 0xbd008000 usable for stack or not ?

Same times board can boot up, but in a very unstable. i use the following setting:

#define CONFIG_SYS_INIT_RAM_ADDR 0xbd000000

Should be 0xbd007000

Quoted 1 line

#define CONFIG_SYS_INIT_RAM_SIZE (32 * SZ_1K)

Should be 4 KiB large.

Quoted 2 lines

#define CONFIG_SYS_INIT_SP_OFFSET \

Quoted 7 lines
Quoted 5 lines

(CONFIG_SYS_INIT_RAM_SIZE - GENERATED_GBL_DATA_SIZE)

#define CONFIG_SYS_INIT_SP_ADDR \

(CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_INIT_SP_OFFSET)

Did you investigate why the board has problems ?

according to the description above by Wills those three defines setup the values correctly for start.S:

#define CONFIG_SYS_INIT_RAM_ADDR 0xbd000000
#define CONFIG_SYS_INIT_RAM_SIZE (32 * SZ_1K)
#define CONFIG_SYS_INIT_SP_ADDR \
(CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_INIT_RAM_SIZE)

Quoted 8 lines

The stack pointer will then be set to the end of the SRAM area with a 16 Byte alignment. The resulting address should be 0xbd007ff0. From this address, the size of gd_t and CONFIG_SYS_MALLOC_F_LEN will be subtracted. The remaining space is available for the initial stack.

Which value did you chose for CONFIG_SYS_MALLOC_F_LEN? It must be big enough to satisfy all malloc requests by the DM stack and small enough to fit in 32k minus stack size and gd_t size.

Careful about those 32k, I think the code which I referenced only uses 4k area.

Quoted 3 lines

Important note: do net set CONFIG_SKIP_LOWLEVEL_INIT yet because that leaves you without initialized RAM or caches. If the setup does not work yet, you likely need to init some extra bits to make the SRAM working.

Best regards,

author
#29 lore raw

PATCH v3 1/4 mips: add base support for atheros ath79 based SOCs

In reply to Daniel Schwierzeck
Quoted 51 lines · Daniel Schwierzeck

Am 27.12.2015 um 12:04 schrieb Marek Vasut:

Quoted 27 lines · Wills Wang
Quoted 16 lines · Marek Vasut
Quoted 15 lines · Wills Wang
Quoted 14 lines · Marek Vasut
Quoted 13 lines · Wills Wang
Quoted 12 lines · Marek Vasut
Quoted 7 lines · Wills Wang
Quoted 1 line

WASP is ar9341.

Please do not top post.

Did you try if the memory is accessible on your platform ? AR9331 I have here has the SRAM at 0xbd007000 , just like that machine in [1] .

I found there is a memory segment at 0xbd000000...0xbd007fff. it's independent of DDR physical memory, can be read and wrote, but hardware can't boot up if don't execute lowlevel_init.S when define CONFIG_SYS_INIT_SP_ADDR=0xbd007000 to set C stack into SRAM.

Quoted 8 lines
Quoted 4 lines
Quoted 3 lines
Quoted 2 lines

Stack grows down, so of course if you put stack at the beginning of SRAM, that cannot work ;-) Put it at the end , 0xbd008000.

This memory segment was mapped circularly at 0xbd000000...0xbdffffff.

So is this area at 0xbd008000 usable for stack or not ?

Same times board can boot up, but in a very unstable. i use the following setting:

#define CONFIG_SYS_INIT_RAM_ADDR 0xbd000000

Should be 0xbd007000

Quoted 9 lines
Quoted 1 line

#define CONFIG_SYS_INIT_RAM_SIZE (32 * SZ_1K)

Should be 4 KiB large.

Quoted 4 lines

#define CONFIG_SYS_INIT_SP_OFFSET \
(CONFIG_SYS_INIT_RAM_SIZE - GENERATED_GBL_DATA_SIZE)
#define CONFIG_SYS_INIT_SP_ADDR \
(CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_INIT_SP_OFFSET)

Did you investigate why the board has problems ?

according to the description above by Wills those three defines setup the values correctly for start.S:

#define CONFIG_SYS_INIT_RAM_ADDR 0xbd000000
#define CONFIG_SYS_INIT_RAM_SIZE (32 * SZ_1K)
#define CONFIG_SYS_INIT_SP_ADDR \
(CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_INIT_RAM_SIZE)

The stack pointer will then be set to the end of the SRAM area with a 16 Byte alignment. The resulting address should be 0xbd007ff0. From this address, the size of gd_t and CONFIG_SYS_MALLOC_F_LEN will be subtracted. The remaining space is available for the initial stack.

Quoted 8 lines

Which value did you chose for CONFIG_SYS_MALLOC_F_LEN? It must be big enough to satisfy all malloc requests by the DM stack and small enough to fit in 32k minus stack size and gd_t size.

Important note: do net set CONFIG_SKIP_LOWLEVEL_INIT yet because that leaves you without initialized RAM or caches. If the setup does not work yet, you likely need to init some extra bits to make the SRAM working.

#define CONFIG_SYS_MALLOC_F_LEN 0x2000
I don't set CONFIG_SKIP_LOWLEVEL_INIT

Signature · 2 lines
Best Regards
Wills
author
#30 lore raw

PATCH v3 2/4 mips: ath79: add serial driver for ar933x SOC

In reply to a message not in the archive

---

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
drivers/serial/Makefile +1 -0
index dd87147..9a7ad89 100644
@@ -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
drivers/serial/serial_ar933x.c new file +274 -0

274 lines not on this page · raw message

Signature · 1 line
1.9.1
#31 lore raw

PATCH v3 2/4 mips: ath79: add serial driver for ar933x SOC

Hi Wills,

Is there any reason that you need to support pre-DM serial driver? It should be safe to support DM only. You may add debug_uart support which might be helpful during debug. The ops for DM serial is different to pre-DM though the name look similar. Please see the comments below.

I worked on mips before I moved to nios very long ago (20 yr). And nios2 mostly followed mips.

I understand there is not device tree control for u-boot on mips yet. But I added it to nios2 recently. It might be worthy if you could add it to mips. You may find the dts binding on Linux kernel. And please add dts binding to doc/ and you might copy them from Linux kernel.

drivers/serial/serial_ar933x.c line 16

Quoted 10 lines
drivers/serial/serial_ar933x.c new file +10 -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>

Please sort the sequence of header files inclusion.

Quoted 54 lines
drivers/serial/serial_ar933x.c new file +54 -0
+
+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},

drivers/serial/serial_ar933x.c line 80

Quoted 10 lines
drivers/serial/serial_ar933x.c new file +10 -0
+	{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},
+};

The requirement of u-boot is much simpler than Linux kernel. For the uart header, you should include only the macros that the driver really used. Or you can add it to the driver directly without the additional header file. The same rule applies to the baudrate tables. You need only some practical rates, not every possible one.

drivers/serial/serial_ar933x.c line 91

Quoted 11 lines
drivers/serial/serial_ar933x.c new file +11 -0
+
+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));
+}
+

For the KSEG1ADDR mapping, which Marek also mentioned, I would suggest rework map_physmem() in asm/io.h on mips to map K1 kernel space, which is very similar to ioremap() on Linux kernel. So that you don't need to map it for every IO.

plat->regs = map_physmem(dev_get_addr(dev),
sizeof(...),
MAP_NOCACHE);

Quoted 5 lines
drivers/serial/serial_ar933x.c new file +5 -0
+static int ar933x_serial_init(void)
+{
+	u32 val;
+
+	/*

drivers/serial/serial_ar933x.c line 106

Quoted 10 lines
drivers/serial/serial_ar933x.c new file +10 -0
+	 * 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);

These might go to the pinctrl driver or board initialization.

Quoted 19 lines
drivers/serial/serial_ar933x.c new file +19 -0
+
+	/*
+	 * 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)
+{

drivers/serial/serial_ar933x.c line 135

Quoted 10 lines
drivers/serial/serial_ar933x.c new file +10 -0
+#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);

This can go to some clock rate in board info during board initialization.

Quoted 8 lines
drivers/serial/serial_ar933x.c new file +8 -0
+	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);

drivers/serial/serial_ar933x.c line 153

Quoted 10 lines
drivers/serial/serial_ar933x.c new file +10 -0
+		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;
+		}
+	}

What happens if not found?

drivers/serial/serial_ar933x.c line 156

Quoted 3 lines
drivers/serial/serial_ar933x.c new file +3 -0
+
+	val  = ((scale & AR933X_UART_CLOCK_SCALE_M)
+			<< AR933X_UART_CLOCK_SCALE_S);

The outer parenthesis is not needed.

Quoted 9 lines
drivers/serial/serial_ar933x.c new file +9 -0
+	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

drivers/serial/serial_ar933x.c line 175

Quoted 10 lines
drivers/serial/serial_ar933x.c new file +10 -0
+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');

Not needed for DM serial.

drivers/serial/serial_ar933x.c line 181

Quoted 6 lines
drivers/serial/serial_ar933x.c new file +6 -0
+#else
+		ar933x_serial_putc('\r');
+#endif
+	do {
+		data = ar933x_read(AR933X_UART_BASE, AR933X_UART_DATA_REG);
+	} while (!(data & AR933X_UART_DATA_TX_CSR));

Return -EAGAIN if not ready for DM serial.

Quoted 9 lines
drivers/serial/serial_ar933x.c new file +9 -0
+
+	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

drivers/serial/serial_ar933x.c line 200

Quoted 10 lines
drivers/serial/serial_ar933x.c new file +10 -0
+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));

Return -EAGAIN if no data available for DM serial.

Quoted 34 lines
drivers/serial/serial_ar933x.c new file +34 -0
+
+	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" },
+	{ }

drivers/serial/serial_ar933x.c line 244

Quoted 10 lines
drivers/serial/serial_ar933x.c new file +10 -0
+};
+
+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,
+};

I understand there might be only a single UART on the ar9331. But it might be better to bind the reg address with U_BOOT_DEVICE() and platform data, or better dts.

Thanks.

Best regards,
Thomas

author
#32 lore raw

PATCH v3 2/4 mips: ath79: add serial driver for ar933x SOC

Quoted 8 lines · Thomas Chou

Hi Wills,

Is there any reason that you need to support pre-DM serial driver? It should be safe to support DM only. You may add debug_uart support which might be helpful during debug. The ops for DM serial is different to pre-DM though the name look similar. Please see the comments below.

I will remove the code about pre-DM serial driver.

Quoted 8 lines

I worked on mips before I moved to nios very long ago (20 yr). And nios2 mostly followed mips.

I understand there is not device tree control for u-boot on mips yet. But I added it to nios2 recently. It might be worthy if you could add it to mips. You may find the dts binding on Linux kernel. And please add dts binding to doc/ and you might copy them from Linux kernel.

I has taken a long time to add base device tree for this patch, but i can't get the driver serial number if don't specify explicitly "aliases" section in dts file. but It seems to not need for ARM device.

Quoted 101 lines

drivers/serial/serial_ar933x.c line 16

Quoted 10 lines
drivers/serial/serial_ar933x.c new file +10 -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>

Please sort the sequence of header files inclusion.

Quoted 54 lines
drivers/serial/serial_ar933x.c new file +54 -0
+
+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},

drivers/serial/serial_ar933x.c line 80

Quoted 10 lines
drivers/serial/serial_ar933x.c new file +10 -0
+    {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},
+};

The requirement of u-boot is much simpler than Linux kernel. For the uart header, you should include only the macros that the driver really used. Or you can add it to the driver directly without the additional header file. The same rule applies to the baudrate tables. You need only some practical rates, not every possible one.

drivers/serial/serial_ar933x.c line 91

Quoted 11 lines
drivers/serial/serial_ar933x.c new file +11 -0
+
+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));
+}
+

For the KSEG1ADDR mapping, which Marek also mentioned, I would suggest rework map_physmem() in asm/io.h on mips to map K1 kernel space, which is very similar to ioremap() on Linux kernel. So that you don't need to map it for every IO.

Quoted 4 lines

plat->regs = map_physmem(dev_get_addr(dev),
sizeof(...),
MAP_NOCACHE);

In MIPS, function "map_physmem" is empty.

Quoted 69 lines
Quoted 5 lines
drivers/serial/serial_ar933x.c new file +5 -0
+static int ar933x_serial_init(void)
+{
+    u32 val;
+
+    /*

drivers/serial/serial_ar933x.c line 106

Quoted 10 lines
drivers/serial/serial_ar933x.c new file +10 -0
+     * 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);

These might go to the pinctrl driver or board initialization.

Quoted 19 lines
drivers/serial/serial_ar933x.c new file +19 -0
+
+    /*
+     * 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)
+{

drivers/serial/serial_ar933x.c line 135

Quoted 10 lines
drivers/serial/serial_ar933x.c new file +10 -0
+#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);

This can go to some clock rate in board info during board initialization.

Quoted 8 lines
drivers/serial/serial_ar933x.c new file +8 -0
+    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);

drivers/serial/serial_ar933x.c line 153

Quoted 10 lines
drivers/serial/serial_ar933x.c new file +10 -0
+        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;
+        }
+    }
Quoted 1 line

What happens if not found?

"scale" and "step" was initialized by "if...else" statement above.

Quoted 101 lines

drivers/serial/serial_ar933x.c line 156

Quoted 4 lines
drivers/serial/serial_ar933x.c new file +3 -0
+
+    val  = ((scale & AR933X_UART_CLOCK_SCALE_M)
+            << AR933X_UART_CLOCK_SCALE_S);

The outer parenthesis is not needed.

Quoted 9 lines
drivers/serial/serial_ar933x.c new file +9 -0
+    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

drivers/serial/serial_ar933x.c line 175

Quoted 10 lines
drivers/serial/serial_ar933x.c new file +10 -0
+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');

Not needed for DM serial.

drivers/serial/serial_ar933x.c line 181

Quoted 6 lines
drivers/serial/serial_ar933x.c new file +6 -0
+#else
+        ar933x_serial_putc('\r');
+#endif
+    do {
+        data = ar933x_read(AR933X_UART_BASE, AR933X_UART_DATA_REG);
+    } while (!(data & AR933X_UART_DATA_TX_CSR));

Return -EAGAIN if not ready for DM serial.

Quoted 9 lines
drivers/serial/serial_ar933x.c new file +9 -0
+
+    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

drivers/serial/serial_ar933x.c line 200

Quoted 10 lines
drivers/serial/serial_ar933x.c new file +10 -0
+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));

Return -EAGAIN if no data available for DM serial.

Quoted 41 lines
drivers/serial/serial_ar933x.c new file +3 -0
+
+    data = ar933x_read(AR933X_UART_BASE, AR933X_UART_DATA_REG);
+    ar933x_write(AR933X_UART_BASE, AR933X_UART_DATA_REG, 

AR933X_UART_DATA_RX_CSR);

drivers/serial/serial_ar933x.c new file +37 -0
+    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,
Quoted 9 lines

drivers/serial/serial_ar933x.c line 244

Quoted 4 lines
drivers/serial/serial_ar933x.c new file +4 -0
+    .probe = ar933x_serial_probe,
+    .ops    = &ar933x_serial_ops,
+    .flags = DM_FLAG_PRE_RELOC,
+};

I understand there might be only a single UART on the ar9331. But it might be better to bind the reg address with U_BOOT_DEVICE() and platform data, or better dts.

The pinctrl and clock drvier is not ready, there is no way to operate clock and gpio resister if use address from device tree.

Quoted 6 lines

Thanks.

Best regards,
Thomas

#33 lore raw

PATCH v3 2/4 mips: ath79: add serial driver for ar933x SOC

Quoted 15 lines · Wills Wang
Quoted 8 lines · Thomas Chou

Hi Wills,

Is there any reason that you need to support pre-DM serial driver? It should be safe to support DM only. You may add debug_uart support which might be helpful during debug. The ops for DM serial is different to pre-DM though the name look similar. Please see the comments below.

I will remove the code about pre-DM serial driver.

Quoted 3 lines

I worked on mips before I moved to nios very long ago (20 yr). And nios2 mostly followed mips.

Quoted 9 lines
Quoted 5 lines

I understand there is not device tree control for u-boot on mips yet. But I added it to nios2 recently. It might be worthy if you could add it to mips. You may find the dts binding on Linux kernel. And please add dts binding to doc/ and you might copy them from Linux kernel.

I has taken a long time to add base device tree for this patch, but i can't get the driver serial number if don't specify explicitly "aliases" section in dts file. but It seems to not need for ARM device.

Quoted 1 line
Quoted 1 line

+

You will need to add "stdout-path=..." property with your serial path to the chosen
node, like this,

	chosen {
		stdout-path = &uart;
	};
Quoted 100 lines
Quoted 100 lines

drivers/serial/serial_ar933x.c line 16

Quoted 9 lines
drivers/serial/serial_ar933x.c new file +9 -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>

Please sort the sequence of header files inclusion.

Quoted 54 lines
drivers/serial/serial_ar933x.c new file +54 -0
+
+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},

drivers/serial/serial_ar933x.c line 80

Quoted 10 lines
drivers/serial/serial_ar933x.c new file +10 -0
+    {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},
+};

The requirement of u-boot is much simpler than Linux kernel. For the uart header, you should include only the macros that the driver really used. Or you can add it to the driver directly without the additional header file. The same rule applies to the baudrate tables. You need only some practical rates, not every possible one.

drivers/serial/serial_ar933x.c line 91

Quoted 11 lines
drivers/serial/serial_ar933x.c new file +11 -0
+
+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));
+}
+

For the KSEG1ADDR mapping, which Marek also mentioned, I would suggest rework map_physmem() in asm/io.h on mips to map K1 kernel space, which is very similar to ioremap() on Linux kernel. So that you don't need to map it for every IO.

Quoted 5 lines
Quoted 4 lines

plat->regs = map_physmem(dev_get_addr(dev),
sizeof(...),
MAP_NOCACHE);

In MIPS, function "map_physmem" is empty.

Yes. But you may improve it to do the real work. For example, not tested,

#define MAP_NOCACHE 1
#define MAP_WRCOMBINE 0
#define MAP_WRBACK 0
#define MAP_WRTHROUGH 0

static inline void *
map_physmem(phys_addr_t paddr, unsigned long len, unsigned long flags)

{
	if (flags)
		return (void *)KSEG1ADDR(paddr);
	else
		return (void *)KSEG0ADDR(paddr);
}
Quoted 181 lines
Quoted 69 lines
Quoted 5 lines
drivers/serial/serial_ar933x.c new file +5 -0
+static int ar933x_serial_init(void)
+{
+    u32 val;
+
+    /*

drivers/serial/serial_ar933x.c line 106

Quoted 10 lines
drivers/serial/serial_ar933x.c new file +10 -0
+     * 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);

These might go to the pinctrl driver or board initialization.

Quoted 19 lines
drivers/serial/serial_ar933x.c new file +19 -0
+
+    /*
+     * 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)
+{

drivers/serial/serial_ar933x.c line 135

Quoted 10 lines
drivers/serial/serial_ar933x.c new file +10 -0
+#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);

This can go to some clock rate in board info during board initialization.

Quoted 8 lines
drivers/serial/serial_ar933x.c new file +8 -0
+    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);

drivers/serial/serial_ar933x.c line 153

Quoted 10 lines
drivers/serial/serial_ar933x.c new file +10 -0
+        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;
+        }
+    }
Quoted 1 line

What happens if not found?

"scale" and "step" was initialized by "if...else" statement above.

Quoted 101 lines

drivers/serial/serial_ar933x.c line 156

Quoted 4 lines
drivers/serial/serial_ar933x.c new file +3 -0
+
+    val  = ((scale & AR933X_UART_CLOCK_SCALE_M)
+            << AR933X_UART_CLOCK_SCALE_S);

The outer parenthesis is not needed.

Quoted 9 lines
drivers/serial/serial_ar933x.c new file +9 -0
+    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

drivers/serial/serial_ar933x.c line 175

Quoted 10 lines
drivers/serial/serial_ar933x.c new file +10 -0
+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');

Not needed for DM serial.

drivers/serial/serial_ar933x.c line 181

Quoted 6 lines
drivers/serial/serial_ar933x.c new file +6 -0
+#else
+        ar933x_serial_putc('\r');
+#endif
+    do {
+        data = ar933x_read(AR933X_UART_BASE, AR933X_UART_DATA_REG);
+    } while (!(data & AR933X_UART_DATA_TX_CSR));

Return -EAGAIN if not ready for DM serial.

Quoted 9 lines
drivers/serial/serial_ar933x.c new file +9 -0
+
+    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

drivers/serial/serial_ar933x.c line 200

Quoted 10 lines
drivers/serial/serial_ar933x.c new file +10 -0
+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));

Return -EAGAIN if no data available for DM serial.

Quoted 41 lines
drivers/serial/serial_ar933x.c new file +3 -0
+
+    data = ar933x_read(AR933X_UART_BASE, AR933X_UART_DATA_REG);
+    ar933x_write(AR933X_UART_BASE, AR933X_UART_DATA_REG,

AR933X_UART_DATA_RX_CSR);

drivers/serial/serial_ar933x.c new file +37 -0
+    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,
Quoted 9 lines

drivers/serial/serial_ar933x.c line 244

Quoted 4 lines
drivers/serial/serial_ar933x.c new file +4 -0
+    .probe = ar933x_serial_probe,
+    .ops    = &ar933x_serial_ops,
+    .flags = DM_FLAG_PRE_RELOC,
+};

I understand there might be only a single UART on the ar9331. But it might be better to bind the reg address with U_BOOT_DEVICE() and platform data, or better dts.

Quoted 2 lines

The pinctrl and clock drvier is not ready, there is no way to operate clock and gpio resister if use address from device tree.

You may add a legacy get_serial_clock() temporarily. And put the reset/pin configuration under mach-ath79. You may improve them with pinctrl and clock drivers.

Best regards,
Thomas

#34 lore raw

PATCH v3 2/4 mips: ath79: add serial driver for ar933x SOC

In reply to Wills Wang

Hi Wills,

There is code to set baud rate in Linux kernel,

drivers/tty/serial/ar933x_uart.c

Best regards,
Thomas

#35 lore raw

PATCH v3 2/4 mips: ath79: add serial driver for ar933x SOC

In reply to Wills Wang

Hi WIlls,

Quoted 194 lines · Wills Wang

---

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
drivers/serial/Makefile +1 -0
index dd87147..9a7ad89 100644
@@ -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
drivers/serial/serial_ar933x.c new file +165 -0
new file mode 100644
index 0000000..6c0d726
@@ -0,0 +1,274 @@
+/*
+ * (C) Copyright 2015
+ * Wills Wang, <[email protected]>
+ *
+ * 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

drivers/serial/serial_ar933x.c line 175

Quoted 10 lines
drivers/serial/serial_ar933x.c new file +10 -0
+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.

drivers/serial/serial_ar933x.c line 181

Quoted 6 lines
drivers/serial/serial_ar933x.c new file +6 -0
+#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.

Quoted 9 lines
drivers/serial/serial_ar933x.c new file +9 -0
+
+       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

drivers/serial/serial_ar933x.c line 200

Quoted 10 lines
drivers/serial/serial_ar933x.c new file +10 -0
+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.

Quoted 75 lines
drivers/serial/serial_ar933x.c new file +74 -1
+
+       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
--
Quoted 2 lines

1.9.1

Regards,
SImon

author
#36 lore raw

PATCH v3 2/4 mips: ath79: add serial driver for ar933x SOC

Quoted 309 lines · Simon Glass

Hi WIlls,

Quoted 194 lines · Wills Wang

---

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

drivers/serial/Makefile +1 -0
index dd87147..9a7ad89 100644
@@ -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
drivers/serial/serial_ar933x.c new file +165 -0
new file mode 100644
index 0000000..6c0d726
@@ -0,0 +1,274 @@
+/*
+ * (C) Copyright 2015
+ * Wills Wang, <[email protected]>
+ *
+ * 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

drivers/serial/serial_ar933x.c line 175

Quoted 10 lines
drivers/serial/serial_ar933x.c new file +10 -0
+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.

drivers/serial/serial_ar933x.c line 181

Quoted 6 lines
drivers/serial/serial_ar933x.c new file +6 -0
+#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.

Quoted 9 lines
drivers/serial/serial_ar933x.c new file +9 -0
+
+       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

drivers/serial/serial_ar933x.c line 200

Quoted 10 lines
drivers/serial/serial_ar933x.c new file +10 -0
+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.

Quoted 71 lines
drivers/serial/serial_ar933x.c new file +71 -0
+
+       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)
+{
Quoted 8 lines
Quoted 6 lines
drivers/serial/serial_ar933x.c new file +3 -1
+       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.

Signature · 2 lines
Best Regards
Wills
author
#37 lore raw

PATCH v3 3/4 mips: ath79: add spi driver

In reply to a message not in the archive

---

Changes in v3: None
Changes in v2: None

 drivers/spi/Kconfig     |   6 ++
 drivers/spi/Makefile    |   1 +
 drivers/spi/ath79_spi.c | 211 ++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 218 insertions(+)
 create mode 100644 drivers/spi/ath79_spi.c
drivers/spi/Kconfig +6 -0
index 2cdb110..04a24ab 100644
@@ -23,6 +23,12 @@ config ALTERA_SPI
 	  IP core. Please find details on the "Embedded Peripherals IP
 	  User Guide" of Altera.
 
+config ATH79_SPI
+	bool "Atheros SPI driver"
+	help
+	  Enable the Atheros SPI driver, used to access SPI NOR flash and
+	  other SPI peripherals on Atheros ar7xxx/ar9xxx SoCs.
+
 config CADENCE_QSPI
 	bool "Cadence QSPI driver"
 	help
drivers/spi/Makefile +1 -0
index 3eca745..7fb2926 100644
@@ -17,6 +17,7 @@ endif
 
 obj-$(CONFIG_ALTERA_SPI) += altera_spi.o
 obj-$(CONFIG_ARMADA100_SPI) += armada100_spi.o
+obj-$(CONFIG_ATH79_SPI) += ath79_spi.o
 obj-$(CONFIG_ATMEL_DATAFLASH_SPI) += atmel_dataflash_spi.o
 obj-$(CONFIG_ATMEL_SPI) += atmel_spi.o
 obj-$(CONFIG_BFIN_SPI) += bfin_spi.o
drivers/spi/ath79_spi.c new file +211 -0

211 lines not on this page · raw message

Signature · 1 line
1.9.1
#38 lore raw

PATCH v3 3/4 mips: ath79: add spi driver

Quoted 2 lines · Wills Wang

---

[...]

Quoted 14 lines
drivers/spi/ath79_spi.c new file +8 -0
new file mode 100644
index 0000000..ddfc807
@@ -0,0 +1,211 @@
+/*
+ * (C) Copyright 2015
+ * Wills Wang, <[email protected]>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>

drivers/spi/ath79_spi.c line 18

Quoted 10 lines
drivers/spi/ath79_spi.c new file +10 -0
+#include <spi.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>
+
+/* CLOCK_DIVIDER = 3 (SPI clock = 200 / 8 ~ 25 MHz) */
+#define SPI_CLK_DIV(x)     ((x >> 1) - 1)

The x needs parenthesis ... (((x) >> 1) - 1)

Quoted 4 lines
drivers/spi/ath79_spi.c new file +4 -0
+
+struct ath79_spi_platdata {
+	void __iomem *regs;
+};

drivers/spi/ath79_spi.c line 32

Quoted 10 lines
drivers/spi/ath79_spi.c new file +10 -0
+
+struct ath79_spi_priv {
+	void __iomem *regs;
+};
+
+static inline u32 ath79_spi_read(struct udevice *bus, u32 offset)
+{
+	struct ath79_spi_priv *priv = dev_get_priv(bus);
+	const void __iomem *base = (void __iomem *)KSEG1ADDR(priv->regs);
+	return readl(base + offset);

Just make this readl(KSEG1ADDR(...)) ?

drivers/spi/ath79_spi.c

Quoted 4 lines
drivers/spi/ath79_spi.c new file +4 -0
+}
+
+static inline void ath79_spi_write(struct udevice *bus, u32 val,
+									u32 

offset)

drivers/spi/ath79_spi.c line 40

Quoted 4 lines
drivers/spi/ath79_spi.c new file +4 -0
+{
+	struct ath79_spi_priv *priv = dev_get_priv(bus);
+	const void __iomem *base = (void __iomem *)KSEG1ADDR(priv->regs);
+	writel(val, base + offset);

DTTO here.

[...]

author
#39 lore raw

PATCH v3 4/4 mips: ath79: add AP121 reference board

In reply to a message not in the archive

---

Changes in v3:
- Convert serial driver to driver model
- Convert spi driver to driver model
- Add support for device tree
- Move SoC specific header files into arch/mips/mach-ath79/include/mach
- Optimize assembly code
- Same code style convertion

Changes in v2:
- Move all SoC specific header files into arch/mips/include/asm/arch-ath79
- Check SOC type and extract common code into arch/mips/mach-ath79
- Add a compatible spi driver
- Move serial driver code into drivers/serial
- Add a reference board implemention

 arch/mips/Kconfig             |  8 +++++
 arch/mips/dts/Makefile        |  2 +-
 arch/mips/dts/ap121.dts       | 37 ++++++++++++++++++++
 arch/mips/dts/ar933x.dtsi     | 64 +++++++++++++++++++++++++++++++++++
 board/ath79/ap121/Kconfig     | 15 ++++++++
 board/ath79/ap121/MAINTAINERS |  6 ++++
 board/ath79/ap121/Makefile    |  8 +++++
 board/ath79/ap121/README      | 18 ++++++++++
 board/ath79/ap121/ap121.c     | 18 ++++++++++
 board/ath79/ap121/config.mk   | 16 +++++++++
 configs/ap121_defconfig       | 42 +++++++++++++++++++++++
 include/configs/ap121.h       | 79 +++++++++++++++++++++++++++++++++++++++++++
 12 files changed, 312 insertions(+), 1 deletion(-)
 create mode 100644 arch/mips/dts/ap121.dts
 create mode 100644 arch/mips/dts/ar933x.dtsi
 create mode 100644 board/ath79/ap121/Kconfig
 create mode 100644 board/ath79/ap121/MAINTAINERS
 create mode 100644 board/ath79/ap121/Makefile
 create mode 100644 board/ath79/ap121/README
 create mode 100644 board/ath79/ap121/ap121.c
 create mode 100644 board/ath79/ap121/config.mk
 create mode 100644 configs/ap121_defconfig
 create mode 100644 include/configs/ap121.h
arch/mips/Kconfig +8 -0
index 7f7e258..09b8709 100644
@@ -51,6 +51,13 @@ config TARGET_PB1X00
 	select SUPPORTS_CPU_MIPS32_R2
 	select SYS_MIPS_CACHE_INIT_RAM_LOAD
 
+config TARGET_AP121
+	bool "Support ap121"
+	select SUPPORTS_BIG_ENDIAN
+	select SUPPORTS_CPU_MIPS32_R1
+	select SUPPORTS_CPU_MIPS32_R2
+	select SYS_MIPS_CACHE_INIT_RAM_LOAD
+
 
 endchoice
 
@@ -59,6 +66,7 @@ source "board/imgtec/malta/Kconfig"
 source "board/micronas/vct/Kconfig"
 source "board/pb1x00/Kconfig"
 source "board/qemu-mips/Kconfig"
+source "board/ath79/ap121/Kconfig"
 
 if MIPS
 
arch/mips/dts/Makefile +1 -1
index 47b6eb5..6f8b413 100644
@@ -2,7 +2,7 @@
 # SPDX-License-Identifier:	GPL-2.0+
 #
 
-dtb-y +=
+dtb-$(CONFIG_TARGET_AP121) += ap121.dtb
 
 targets += $(dtb-y)
 
arch/mips/dts/ap121.dts new file +37 -0
new file mode 100644
index 0000000..769458a
@@ -0,0 +1,37 @@
+/dts-v1/;
+#include "ar933x.dtsi"
+
+/ {
+	model = "AP121 Reference Board";
+	compatible = "ath79,ap121", "ath79,ar933x";
+
+	aliases {
+		spi0 = &spi0;
+		serial0 = &uart0;
+	};
+
+	chosen {
+		stdout-path = "serial0:115200n8";
+	};
+};
+
+&xtal {
+	clock-frequency = <25000000>;
+};
+
+&uart0 {
+	status = "okay";
+};
+
+&spi0 {
+	spi-max-frequency = <25000000>;
+	status = "okay";
+	spi-flash at 0 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "spi-flash";
+		memory-map = <0x9f000000 0x00800000>;
+		spi-max-frequency = <25000000>;
+		reg = <0>;
+	};
+};
arch/mips/dts/ar933x.dtsi new file +64 -0

64 lines not on this page · raw message

board/ath79/ap121/Kconfig new file +15 -0
new file mode 100644
index 0000000..88d9eff
@@ -0,0 +1,15 @@
+if TARGET_AP121
+
+config SYS_BOARD
+	default "ap121"
+
+config SYS_VENDOR
+	default "ath79"
+
+config SYS_SOC
+	default "ath79"
+
+config SYS_CONFIG_NAME
+	default "ap121"
+
+endif
board/ath79/ap121/MAINTAINERS new file +6 -0
new file mode 100644
index 0000000..319b521
@@ -0,0 +1,6 @@
+AP121 BOARD
+M:	Wills Wang <[email protected]>
+S:	Maintained
+F:	board/ath79/ap121/
+F:	include/configs/ap121.h
+F:	configs/ap121_defconfig
board/ath79/ap121/Makefile new file +8 -0
new file mode 100644
index 0000000..9132118
@@ -0,0 +1,8 @@
+#
+# (C) Copyright 2003-2006
+# Wolfgang Denk, DENX Software Engineering, wd at denx.de.
+#
+# SPDX-License-Identifier:	GPL-2.0+
+#
+
+obj-y	= ap121.o
board/ath79/ap121/README new file +18 -0
new file mode 100644
index 0000000..104850f
@@ -0,0 +1,18 @@
+ATHEROS AP121
+==================
+
+Supported hardware: AP121 referance board.
+
+Files of the AP121 port
+--------------------------
+
+arch/mips/mach-ath79/ar933x/	- The CPU support code for the Atheros ar933x
+arch/mips/include/asm/arch-ath79	- Header files for the Atheros ath79
+board/ath79/ap121/	- AP121 board specific files
+include/configs/ap121.h	- AP121 configuration file
+
+Configure
+-------------------
+
+To configure for the current board
+	make ap121_defconfig
board/ath79/ap121/ap121.c new file +18 -0
new file mode 100644
index 0000000..3a3d782
@@ -0,0 +1,18 @@
+/*
+ * (C) Copyright 2015
+ * Wills Wang, <[email protected]>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <command.h>
+#include <asm/mipsregs.h>
+#include <asm/addrspace.h>
+#include <asm/io.h>
+
+int checkboard(void)
+{
+	puts("Board: AP121\n");
+	return 0;
+}
board/ath79/ap121/config.mk new file +16 -0
new file mode 100644
index 0000000..f7dd3b7
@@ -0,0 +1,16 @@
+#
+# (C) Copyright 2003
+# Wolfgang Denk, DENX Software Engineering, wd at denx.de.
+#
+# SPDX-License-Identifier:	GPL-2.0+
+#
+
+#
+# AP121 referance board, MIPS32 core
+#
+
+# ROM version
+CONFIG_SYS_TEXT_BASE = 0x9f000000
+
+# RAM version
+#CONFIG_SYS_TEXT_BASE = 0x80010000
configs/ap121_defconfig new file +42 -0

42 lines not on this page · raw message

include/configs/ap121.h new file +79 -0

79 lines not on this page · raw message

Signature · 1 line
1.9.1