From 2d4cf6d95deae61f0d55ec7a8c2b746ebd4e2c1b Mon Sep 17 00:00:00 2001 From: Antony Pavlov Date: Tue, 7 May 2013 12:51:25 +0400 Subject: [PATCH 01/15] MIPS: xburst: use common serial code The Ingenic JZ4740, JZ4755 and JZ4770 SoCs use the same IP core for UART interface. This IP core is NS16550-compatible, but it needs small workaround. This commit moves the UART code for Ingenic SoCs from board level to machine level. So the code can be reused for different boards or even different SoCs. Signed-off-by: Antony Pavlov Signed-off-by: Sascha Hauer --- arch/mips/mach-xburst/Makefile | 1 + arch/mips/mach-xburst/include/mach/devices.h | 8 +++ arch/mips/mach-xburst/serial.c | 60 ++++++++++++++++++++ 3 files changed, 69 insertions(+) create mode 100644 arch/mips/mach-xburst/include/mach/devices.h create mode 100644 arch/mips/mach-xburst/serial.c diff --git a/arch/mips/mach-xburst/Makefile b/arch/mips/mach-xburst/Makefile index e5634ba9c..3e0cd7324 100644 --- a/arch/mips/mach-xburst/Makefile +++ b/arch/mips/mach-xburst/Makefile @@ -1 +1,2 @@ +obj-y += serial.o obj-$(CONFIG_CPU_JZ4755) += csrc-jz4750.o reset-jz4750.o diff --git a/arch/mips/mach-xburst/include/mach/devices.h b/arch/mips/mach-xburst/include/mach/devices.h new file mode 100644 index 000000000..931749d42 --- /dev/null +++ b/arch/mips/mach-xburst/include/mach/devices.h @@ -0,0 +1,8 @@ +#ifndef __MACH_XBURST_DEVICES_H +#define __MACH_XBURST_DEVICES_H + +#include + +struct device_d *jz_add_uart(int id, unsigned long base, unsigned int clock); + +#endif /* __MACH_XBURST_DEVICES_H */ diff --git a/arch/mips/mach-xburst/serial.c b/arch/mips/mach-xburst/serial.c new file mode 100644 index 000000000..acf564846 --- /dev/null +++ b/arch/mips/mach-xburst/serial.c @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2013 Antony Pavlov + * + * Based on the linux kernel JZ4740 serial support: + * Copyright (C) 2010, Lars-Peter Clausen + * + * This file is part of barebox. + * See file CREDITS for list of people who contributed to this project. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include +#include +#include +#include + +#define JZ_UART_SHIFT 2 + +#define ier (1 << JZ_UART_SHIFT) +#define fcr (2 << JZ_UART_SHIFT) + +static void jz_serial_reg_write(unsigned int val, unsigned long base, + unsigned char reg_offset) +{ + switch (reg_offset) { + case fcr: + val |= 0x10; /* Enable uart module */ + break; + case ier: + val |= (val & 0x4) << 2; + break; + default: + break; + } + + writeb(val & 0xff, (void *)(base + reg_offset)); +} + +struct device_d *jz_add_uart(int id, unsigned long base, unsigned int clock) +{ + struct NS16550_plat *serial_plat; + + serial_plat = xzalloc(sizeof(*serial_plat)); + + serial_plat->shift = JZ_UART_SHIFT; + serial_plat->reg_write = &jz_serial_reg_write; + serial_plat->clock = clock; + + return add_ns16550_device(id, base, 8 << JZ_UART_SHIFT, + IORESOURCE_MEM_8BIT, serial_plat); +} From 8b35646356f778287c11971cc8d464aa579f0421 Mon Sep 17 00:00:00 2001 From: Antony Pavlov Date: Tue, 7 May 2013 12:51:26 +0400 Subject: [PATCH 02/15] MIPS: rzx50: switch to common mach-xburst serial code Signed-off-by: Antony Pavlov Signed-off-by: Sascha Hauer --- arch/mips/boards/rzx50/serial.c | 37 ++------------------------------- 1 file changed, 2 insertions(+), 35 deletions(-) diff --git a/arch/mips/boards/rzx50/serial.c b/arch/mips/boards/rzx50/serial.c index 5230aaa8c..129806d5a 100644 --- a/arch/mips/boards/rzx50/serial.c +++ b/arch/mips/boards/rzx50/serial.c @@ -16,47 +16,14 @@ */ #include -#include -#include #include -#include +#include #include -#include -#include - -#define JZ4750D_UART_SHIFT 2 - -#define ier (1 << JZ4750D_UART_SHIFT) -#define fcr (2 << JZ4750D_UART_SHIFT) - -static void jz4750d_serial_reg_write(unsigned int val, unsigned long base, - unsigned char reg_offset) -{ - switch (reg_offset) { - case fcr: - val |= 0x10; /* Enable uart module */ - break; - case ier: - val |= (val & 0x4) << 2; - break; - default: - break; - } - - writeb(val & 0xff, (void *)(base + reg_offset)); -} - -static struct NS16550_plat serial_plat = { - .clock = 12000000, - .shift = JZ4750D_UART_SHIFT, - .reg_write = &jz4750d_serial_reg_write, -}; static int rzx50_console_init(void) { /* Register the serial port */ - add_ns16550_device(DEVICE_ID_DYNAMIC, UART1_BASE, 8 << JZ4750D_UART_SHIFT, - IORESOURCE_MEM_8BIT, &serial_plat); + jz_add_uart(DEVICE_ID_DYNAMIC, UART1_BASE, 12000000); return 0; } From 74c4acea0dbc8a270e584c01f13f61dcc87e4cbd Mon Sep 17 00:00:00 2001 From: Antony Pavlov Date: Sun, 12 May 2013 23:54:03 +0400 Subject: [PATCH 03/15] of: separate out "generic" memory bank adding This patch separates out the "generic" memory segment registration function (of_add_memory_bank()) from of_add_memory(). The MIPS architecture has different view on memory resources than the ARM and PPC architectures so the "generic" of_add_memory_bank() is unusable for the MIPS architecture. We can add MIPS-specific of_add_memory_bank() into arch/mips code. Signed-off-by: Antony Pavlov Signed-off-by: Sascha Hauer --- drivers/of/Kconfig | 5 +++++ drivers/of/Makefile | 1 + drivers/of/base.c | 8 +------- drivers/of/mem_generic.c | 15 +++++++++++++++ include/of.h | 2 ++ 5 files changed, 24 insertions(+), 7 deletions(-) create mode 100644 drivers/of/mem_generic.c diff --git a/drivers/of/Kconfig b/drivers/of/Kconfig index 56762e4f6..ffe063e0b 100644 --- a/drivers/of/Kconfig +++ b/drivers/of/Kconfig @@ -1,6 +1,11 @@ config OFTREE bool +config OFTREE_MEM_GENERIC + depends on OFTREE + depends on PPC || ARM + def_bool y + config DTC bool diff --git a/drivers/of/Makefile b/drivers/of/Makefile index d16a94624..c81bbec89 100644 --- a/drivers/of/Makefile +++ b/drivers/of/Makefile @@ -1,4 +1,5 @@ obj-y += base.o fdt.o +obj-$(CONFIG_OFTREE_MEM_GENERIC) += mem_generic.o obj-$(CONFIG_GPIOLIB) += gpio.o obj-y += partition.o obj-y += of_net.o diff --git a/drivers/of/base.c b/drivers/of/base.c index 838354982..1158132fa 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c @@ -873,7 +873,6 @@ int of_add_memory(struct device_node *node, bool dump) int na, nc; const __be32 *reg, *endp; int len, r = 0, ret; - static char str[6]; const char *device_type; ret = of_property_read_string(node, "device_type", &device_type); @@ -900,12 +899,7 @@ int of_add_memory(struct device_node *node, bool dump) if (size == 0) continue; - sprintf(str, "ram%d", r); - - barebox_add_memory_bank(str, base, size); - - if (dump) - pr_info("%s: %s: 0x%llx@0x%llx\n", node->name, str, size, base); + of_add_memory_bank(node, dump, r, base, size); r++; } diff --git a/drivers/of/mem_generic.c b/drivers/of/mem_generic.c new file mode 100644 index 000000000..9094243c0 --- /dev/null +++ b/drivers/of/mem_generic.c @@ -0,0 +1,15 @@ +#include +#include +#include + +void of_add_memory_bank(struct device_node *node, bool dump, int r, + u64 base, u64 size) +{ + static char str[6]; + + sprintf(str, "ram%d", r); + barebox_add_memory_bank(str, base, size); + + if (dump) + pr_info("%s: %s: 0x%llx@0x%llx\n", node->name, str, size, base); +} diff --git a/include/of.h b/include/of.h index 4dcf37e14..e0fc768e9 100644 --- a/include/of.h +++ b/include/of.h @@ -180,6 +180,8 @@ int of_device_is_stdout_path(struct device_d *dev); const char *of_get_model(void); void *of_flatten_dtb(struct device_node *node); int of_add_memory(struct device_node *node, bool dump); +void of_add_memory_bank(struct device_node *node, bool dump, int r, + u64 base, u64 size); #else static inline int of_parse_partitions(struct cdev *cdev, struct device_node *node) From 6fe6d9fdc2ef89ee92cc40b2114b21cdff9e91ca Mon Sep 17 00:00:00 2001 From: Antony Pavlov Date: Sun, 12 May 2013 23:54:04 +0400 Subject: [PATCH 04/15] MIPS: add initial device tree support Signed-off-by: Antony Pavlov Signed-off-by: Sascha Hauer --- arch/mips/Kconfig | 8 +++++ arch/mips/Makefile | 12 ++++++++ arch/mips/boot/Makefile | 2 ++ arch/mips/boot/dtb.c | 61 +++++++++++++++++++++++++++++++++++++ arch/mips/dts/Makefile | 10 ++++++ arch/mips/dts/skeleton.dtsi | 13 ++++++++ arch/mips/lib/barebox.lds.S | 2 ++ 7 files changed, 108 insertions(+) create mode 100644 arch/mips/boot/dtb.c create mode 100644 arch/mips/dts/Makefile create mode 100644 arch/mips/dts/skeleton.dtsi diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 947edcf6f..d58b804b9 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -23,6 +23,14 @@ config GENERIC_LINKER_SCRIPT menu "Machine selection" +config BUILTIN_DTB + bool "link a DTB into the barebox image" + depends on OFTREE + +config BUILTIN_DTB_NAME + string "DTB to build into the barebox image" + depends on BUILTIN_DTB + choice prompt "System type" default MACH_MIPS_MALTA diff --git a/arch/mips/Makefile b/arch/mips/Makefile index 3c565a48a..c038933cb 100644 --- a/arch/mips/Makefile +++ b/arch/mips/Makefile @@ -113,6 +113,8 @@ common-y += $(BOARD) $(MACH) common-y += arch/mips/lib/ common-y += arch/mips/boot/ +common-$(CONFIG_BUILTIN_DTB) += arch/mips/dts/ + CPPFLAGS += $(cflags-y) CFLAGS += $(cflags-y) @@ -127,4 +129,14 @@ zbarebox.S zbarebox.bin zbarebox: barebox.bin archclean: $(MAKE) $(clean)=$(pbl) +dts := arch/mips/dts + +%.dtb: scripts + $(Q)$(MAKE) $(build)=$(dts) $(dts)/$@ + +dtbs: scripts + $(Q)$(MAKE) $(build)=$(dts) dtbs + +KBUILD_DTBS := dtbs + KBUILD_IMAGE ?= $(KBUILD_BINARY) diff --git a/arch/mips/boot/Makefile b/arch/mips/boot/Makefile index 6b093f1e0..b865b10f8 100644 --- a/arch/mips/boot/Makefile +++ b/arch/mips/boot/Makefile @@ -1,4 +1,6 @@ obj-y += start.o obj-y += main_entry.o +obj-$(CONFIG_BUILTIN_DTB) += dtb.o + pbl-y += start-pbl.o main_entry-pbl.o diff --git a/arch/mips/boot/dtb.c b/arch/mips/boot/dtb.c new file mode 100644 index 000000000..c1962bfd0 --- /dev/null +++ b/arch/mips/boot/dtb.c @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2013 Antony Pavlov + * + * Based on arch/arm/cpu/dtb.c: + * Copyright (C) 2013 Sascha Hauer , Pengutronix + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ +#include +#include +#include +#include +#include + +void of_add_memory_bank(struct device_node *node, bool dump, int r, + u64 base, u64 size) +{ + static char str[12]; + + sprintf(str, "kseg0_ram%d", r); + barebox_add_memory_bank(str, KSEG0 | base, size); + + sprintf(str, "kseg1_ram%d", r); + barebox_add_memory_bank(str, KSEG1 | base, size); + + if (dump) + pr_info("%s: %s: 0x%llx@0x%llx\n", node->name, str, size, base); +} + +extern char __dtb_start[]; + +static int of_mips_init(void) +{ + struct device_node *root; + + root = of_get_root_node(); + if (root) + return 0; + + root = of_unflatten_dtb(NULL, __dtb_start); + if (root) { + pr_debug("using internal DTB\n"); + of_set_root_node(root); + if (IS_ENABLED(CONFIG_OFDEVICE)) + of_probe(); + } + + return 0; +} +core_initcall(of_mips_init); diff --git a/arch/mips/dts/Makefile b/arch/mips/dts/Makefile new file mode 100644 index 000000000..3ee89247e --- /dev/null +++ b/arch/mips/dts/Makefile @@ -0,0 +1,10 @@ + +BUILTIN_DTB := $(patsubst "%",%,$(CONFIG_BUILTIN_DTB_NAME)).dtb.o +obj-$(CONFIG_BUILTIN_DTB) += $(BUILTIN_DTB) + +targets += dtbs +targets += $(dtb-y) + +dtbs: $(addprefix $(obj)/, $(dtb-y)) + +clean-files := *.dtb *.dtb.S diff --git a/arch/mips/dts/skeleton.dtsi b/arch/mips/dts/skeleton.dtsi new file mode 100644 index 000000000..b41d241de --- /dev/null +++ b/arch/mips/dts/skeleton.dtsi @@ -0,0 +1,13 @@ +/* + * Skeleton device tree; the bare minimum needed to boot; just include and + * add a compatible value. The bootloader will typically populate the memory + * node. + */ + +/ { + #address-cells = <1>; + #size-cells = <1>; + chosen { }; + aliases { }; + memory { device_type = "memory"; reg = <0 0>; }; +}; diff --git a/arch/mips/lib/barebox.lds.S b/arch/mips/lib/barebox.lds.S index 5b3d45dc3..bc78d2be8 100644 --- a/arch/mips/lib/barebox.lds.S +++ b/arch/mips/lib/barebox.lds.S @@ -69,6 +69,8 @@ SECTIONS __usymtab : { BAREBOX_SYMS } __usymtab_end = .; + .dtb : { BAREBOX_DTB() } + _edata = .; . = ALIGN(4); __bss_start = .; From 6cdc8f4b02ffcfa9e7c5305dbb1f1f6e66371692 Mon Sep 17 00:00:00 2001 From: Antony Pavlov Date: Sun, 12 May 2013 23:54:05 +0400 Subject: [PATCH 05/15] MIPS: qemu-malta: add device tree support Signed-off-by: Antony Pavlov Signed-off-by: Sascha Hauer --- arch/mips/boards/qemu-malta/init.c | 11 ----------- arch/mips/dts/qemu-malta.dts | 12 ++++++++++++ 2 files changed, 12 insertions(+), 11 deletions(-) create mode 100644 arch/mips/dts/qemu-malta.dts diff --git a/arch/mips/boards/qemu-malta/init.c b/arch/mips/boards/qemu-malta/init.c index fb4472fe8..db26b3b5c 100644 --- a/arch/mips/boards/qemu-malta/init.c +++ b/arch/mips/boards/qemu-malta/init.c @@ -20,21 +20,10 @@ #include #include #include -#include #include #include -#include #include #include -#include - -static int malta_mem_init(void) -{ - mips_add_ram0(SZ_256M); - - return 0; -} -mem_initcall(malta_mem_init); static int malta_devices_init(void) { diff --git a/arch/mips/dts/qemu-malta.dts b/arch/mips/dts/qemu-malta.dts new file mode 100644 index 000000000..c4dcf056c --- /dev/null +++ b/arch/mips/dts/qemu-malta.dts @@ -0,0 +1,12 @@ +/dts-v1/; + +/include/ "skeleton.dtsi" + +/ { + model = "qemu malta"; + compatible = "qemu,malta"; + + memory { + reg = <0x00000000 0x10000000>; + }; +}; From e99906d846feb755a0eb098b801083e925ab49af Mon Sep 17 00:00:00 2001 From: Antony Pavlov Date: Sun, 12 May 2013 23:54:06 +0400 Subject: [PATCH 06/15] MIPS: qemu-malta_defconfig: enable OF support Also enable iomem. Signed-off-by: Antony Pavlov Signed-off-by: Sascha Hauer --- arch/mips/configs/qemu-malta_defconfig | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/arch/mips/configs/qemu-malta_defconfig b/arch/mips/configs/qemu-malta_defconfig index 7dab96993..18c840d7c 100644 --- a/arch/mips/configs/qemu-malta_defconfig +++ b/arch/mips/configs/qemu-malta_defconfig @@ -1,3 +1,5 @@ +CONFIG_BUILTIN_DTB=y +CONFIG_BUILTIN_DTB_NAME="qemu-malta" CONFIG_PBL_IMAGE=y CONFIG_STACK_SIZE=0x7000 CONFIG_BROKEN=y @@ -23,22 +25,25 @@ CONFIG_CMD_MENU=y CONFIG_CMD_MENU_MANAGEMENT=y CONFIG_CMD_PASSWD=y CONFIG_CMD_TIME=y +CONFIG_CMD_TFTP=y CONFIG_CMD_ECHO_E=y CONFIG_CMD_LOADB=y CONFIG_CMD_LOADY=y CONFIG_CMD_MEMINFO=y +CONFIG_CMD_IOMEM=y CONFIG_CMD_CRC=y CONFIG_CMD_CRC_CMP=y CONFIG_CMD_MD5SUM=y CONFIG_CMD_SHA1SUM=y CONFIG_CMD_SHA256SUM=y -CONFIG_CMD_MTEST=y CONFIG_CMD_FLASH=y -CONFIG_CMD_BOOTM_ZLIB=y -CONFIG_CMD_BOOTM_BZLIB=y CONFIG_CMD_BOOTM_SHOW_TYPE=y CONFIG_CMD_RESET=y CONFIG_CMD_GO=y +CONFIG_CMD_OFTREE=y +CONFIG_CMD_OF_PROPERTY=y +CONFIG_CMD_OF_NODE=y +CONFIG_CMD_MTEST=y CONFIG_CMD_TIMEOUT=y CONFIG_CMD_PARTITION=y CONFIG_CMD_UNCOMPRESS=y @@ -46,18 +51,18 @@ CONFIG_NET=y CONFIG_NET_DHCP=y CONFIG_NET_NFS=y CONFIG_NET_PING=y -CONFIG_CMD_TFTP=y -CONFIG_FS_TFTP=y CONFIG_NET_NETCONSOLE=y CONFIG_NET_RESOLV=y +CONFIG_OFDEVICE=y # CONFIG_SPI is not set +CONFIG_MTD=y CONFIG_DRIVER_CFI=y # CONFIG_DRIVER_CFI_AMD is not set # CONFIG_DRIVER_CFI_BANK_WIDTH_1 is not set # CONFIG_DRIVER_CFI_BANK_WIDTH_2 is not set CONFIG_CFI_BUFFER_WRITE=y -CONFIG_MTD=y CONFIG_FS_CRAMFS=y +CONFIG_FS_TFTP=y CONFIG_FS_FAT=y CONFIG_FS_FAT_WRITE=y CONFIG_FS_FAT_LFN=y From de9afb4d6e7bf0c70ddcbe47dfd9ab02b27cf2ba Mon Sep 17 00:00:00 2001 From: Antony Pavlov Date: Sun, 26 May 2013 15:26:59 +0400 Subject: [PATCH 07/15] MIPS: rzx50: add trivial board_pbl_start Signed-off-by: Antony Pavlov Signed-off-by: Sascha Hauer --- .../rzx50/include/board/board_pbl_start.h | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 arch/mips/boards/rzx50/include/board/board_pbl_start.h diff --git a/arch/mips/boards/rzx50/include/board/board_pbl_start.h b/arch/mips/boards/rzx50/include/board/board_pbl_start.h new file mode 100644 index 000000000..cba3e7f47 --- /dev/null +++ b/arch/mips/boards/rzx50/include/board/board_pbl_start.h @@ -0,0 +1,34 @@ +/* + * Startup Code for Ritmix RZX-50 board + * + * Copyright (C) 2013 Antony Pavlov + * + * This file is part of barebox. + * See file CREDITS for list of people who contributed to this project. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include + + .macro board_pbl_start + .set push + .set noreorder + + mips_disable_interrupts + + /* CPU/SoC specific setup ... */ + /* ... absent */ + + copy_to_link_location pbl_start + + .set pop + .endm From 41448848fc3f40d11191787a686038d8ba0531a4 Mon Sep 17 00:00:00 2001 From: Antony Pavlov Date: Sun, 26 May 2013 15:27:00 +0400 Subject: [PATCH 08/15] MIPS: XBurst: enable pbl support Signed-off-by: Antony Pavlov Signed-off-by: Sascha Hauer --- arch/mips/Kconfig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index d58b804b9..555dbb2f8 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -61,6 +61,8 @@ config MACH_MIPS_XBURST select SYS_SUPPORTS_32BIT_KERNEL select DRIVER_SERIAL_NS16550 select HAS_DEBUG_LL + select HAVE_PBL_IMAGE + select HAVE_IMAGE_COMPRESSION endchoice source arch/mips/mach-malta/Kconfig From 77bcb1fa006085b42b11dbd5816609ac01c623ae Mon Sep 17 00:00:00 2001 From: Antony Pavlov Date: Sun, 26 May 2013 15:27:01 +0400 Subject: [PATCH 09/15] MIPS: rzx50: enable pbl in defconfig Also enable the iomem and poweroff commands. Signed-off-by: Antony Pavlov Signed-off-by: Sascha Hauer --- arch/mips/configs/rzx50_defconfig | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/mips/configs/rzx50_defconfig b/arch/mips/configs/rzx50_defconfig index 722d977f5..5d994c76e 100644 --- a/arch/mips/configs/rzx50_defconfig +++ b/arch/mips/configs/rzx50_defconfig @@ -1,4 +1,5 @@ CONFIG_MACH_MIPS_XBURST=y +CONFIG_PBL_IMAGE=y CONFIG_BAUDRATE=57600 CONFIG_GLOB=y CONFIG_HUSH_FANCY_PROMPT=y @@ -14,6 +15,7 @@ CONFIG_CMD_LOADY=y CONFIG_CMD_LOADS=y CONFIG_CMD_SAVES=y CONFIG_CMD_MEMINFO=y +CONFIG_CMD_IOMEM=y CONFIG_CMD_MD5SUM=y CONFIG_CMD_BOOTM_SHOW_TYPE=y CONFIG_CMD_BOOTM_VERBOSE=y @@ -22,6 +24,7 @@ CONFIG_CMD_BOOTM_OFTREE=y CONFIG_CMD_BOOTM_OFTREE_UIMAGE=y CONFIG_CMD_UIMAGE=y CONFIG_CMD_RESET=y +CONFIG_CMD_POWEROFF=y CONFIG_CMD_GO=y # CONFIG_SPI is not set CONFIG_SHA1=y From df308bd4bfadf8a5dd29f6a4f9a29cc459e00ad3 Mon Sep 17 00:00:00 2001 From: Antony Pavlov Date: Thu, 30 May 2013 16:11:29 +0400 Subject: [PATCH 10/15] MIPS: asm/mipsregs.h: remove unused stuff In barebox we have no CONFIG_MIPS_MT_SMTC Kconfig option. So remove the code under this macro. Signed-off-by: Antony Pavlov Signed-off-by: Sascha Hauer --- arch/mips/include/asm/mipsregs.h | 8 -------- 1 file changed, 8 deletions(-) diff --git a/arch/mips/include/asm/mipsregs.h b/arch/mips/include/asm/mipsregs.h index 608f19bda..f9238607a 100644 --- a/arch/mips/include/asm/mipsregs.h +++ b/arch/mips/include/asm/mipsregs.h @@ -673,19 +673,11 @@ do { \ #define write_c0_compare3(val) __write_32bit_c0_register($11, 7, val) #define read_c0_status() __read_32bit_c0_register($12, 0) -#ifdef CONFIG_MIPS_MT_SMTC -#define write_c0_status(val) \ -do { \ - __write_32bit_c0_register($12, 0, val); \ - __ehb(); \ -} while (0) -#else /* * Legacy non-SMTC code, which may be hazardous * but which might not support EHB */ #define write_c0_status(val) __write_32bit_c0_register($12, 0, val) -#endif /* CONFIG_MIPS_MT_SMTC */ #define read_c0_cause() __read_32bit_c0_register($13, 0) #define write_c0_cause(val) __write_32bit_c0_register($13, 0, val) From 59fe549733fb21f1e669bea148dc8c7899890844 Mon Sep 17 00:00:00 2001 From: Oleksij Rempel Date: Thu, 30 May 2013 20:18:40 +0200 Subject: [PATCH 11/15] MIPS: add Atheros ar531x family support Signed-off-by: Oleksij Rempel Signed-off-by: Antony Pavlov Signed-off-by: Sascha Hauer --- arch/mips/Kconfig | 9 + arch/mips/Makefile | 2 + arch/mips/mach-ar231x/Kconfig | 7 + arch/mips/mach-ar231x/Makefile | 3 + arch/mips/mach-ar231x/ar231x.c | 195 +++++++++++ arch/mips/mach-ar231x/ar231x_reset.c | 73 +++++ arch/mips/mach-ar231x/board.c | 188 +++++++++++ .../mach-ar231x/include/mach/ar2312_regs.h | 302 ++++++++++++++++++ .../include/mach/ar231x_platform.h | 104 ++++++ 9 files changed, 883 insertions(+) create mode 100644 arch/mips/mach-ar231x/Kconfig create mode 100644 arch/mips/mach-ar231x/Makefile create mode 100644 arch/mips/mach-ar231x/ar231x.c create mode 100644 arch/mips/mach-ar231x/ar231x_reset.c create mode 100644 arch/mips/mach-ar231x/board.c create mode 100644 arch/mips/mach-ar231x/include/mach/ar2312_regs.h create mode 100644 arch/mips/mach-ar231x/include/mach/ar231x_platform.h diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 555dbb2f8..2e44619a0 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -45,6 +45,14 @@ config MACH_MIPS_MALTA select SYS_SUPPORTS_BIG_ENDIAN select HAS_DEBUG_LL +config MACH_MIPS_AR231X + bool "Atheros ar231x-based boards" + select SYS_HAS_CPU_MIPS32_R1 + select SYS_SUPPORTS_32BIT_KERNEL + select SYS_SUPPORTS_BIG_ENDIAN + select CSRC_R4K_LIB + select DRIVER_SERIAL_NS16550 + config MACH_MIPS_BCM47XX bool "Broadcom BCM47xx-based boards" select CSRC_R4K_LIB @@ -66,6 +74,7 @@ config MACH_MIPS_XBURST endchoice source arch/mips/mach-malta/Kconfig +source arch/mips/mach-ar231x/Kconfig source arch/mips/mach-bcm47xx/Kconfig source arch/mips/mach-xburst/Kconfig diff --git a/arch/mips/Makefile b/arch/mips/Makefile index c038933cb..135259f4d 100644 --- a/arch/mips/Makefile +++ b/arch/mips/Makefile @@ -72,6 +72,8 @@ LDFLAGS_barebox += -nostdlib machine-$(CONFIG_MACH_MIPS_MALTA) := malta board-$(CONFIG_BOARD_QEMU_MALTA) := qemu-malta +machine-$(CONFIG_MACH_MIPS_AR231X) := ar231x + machine-$(CONFIG_MACH_MIPS_BCM47XX) := bcm47xx board-$(CONFIG_BOARD_DLINK_DIR320) := dlink-dir-320 diff --git a/arch/mips/mach-ar231x/Kconfig b/arch/mips/mach-ar231x/Kconfig new file mode 100644 index 000000000..7694fe287 --- /dev/null +++ b/arch/mips/mach-ar231x/Kconfig @@ -0,0 +1,7 @@ +if MACH_MIPS_AR231X + +config ARCH_TEXT_BASE + hex + default 0xa0800000 + +endif diff --git a/arch/mips/mach-ar231x/Makefile b/arch/mips/mach-ar231x/Makefile new file mode 100644 index 000000000..eba8e818b --- /dev/null +++ b/arch/mips/mach-ar231x/Makefile @@ -0,0 +1,3 @@ +obj-y += ar231x.o +obj-y += board.o +obj-y += ar231x_reset.o diff --git a/arch/mips/mach-ar231x/ar231x.c b/arch/mips/mach-ar231x/ar231x.c new file mode 100644 index 000000000..ca912bf0e --- /dev/null +++ b/arch/mips/mach-ar231x/ar231x.c @@ -0,0 +1,195 @@ +/* + * Based on Linux driver: + * Copyright (C) 2003 Atheros Communications, Inc., All Rights Reserved. + * Copyright (C) 2006 FON Technology, SL. + * Copyright (C) 2006 Imre Kaloz + * Copyright (C) 2006-2009 Felix Fietkau + * Ported to Barebox: + * Copyright (C) 2013 Oleksij Rempel + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include +#include +#include +#include +#include +#include + +struct ar231x_board_data ar231x_board; + +/* + * This table is indexed by bits 5..4 of the CLOCKCTL1 register + * to determine the predevisor value. + */ +static int CLOCKCTL1_PREDIVIDE_TABLE[4] = { 1, 2, 4, 5 }; + +static unsigned int +ar2312_cpu_frequency(void) +{ + unsigned int predivide_mask, predivide_shift; + unsigned int multiplier_mask, multiplier_shift; + unsigned int clock_ctl1, pre_divide_select, pre_divisor, multiplier; + unsigned int doubler_mask; + u32 devid; + + devid = __raw_readl((char *)KSEG1ADDR(AR2312_REV)); + devid &= AR2312_REV_MAJ; + devid >>= AR2312_REV_MAJ_S; + if (devid == AR2312_REV_MAJ_AR2313) { + predivide_mask = AR2313_CLOCKCTL1_PREDIVIDE_MASK; + predivide_shift = AR2313_CLOCKCTL1_PREDIVIDE_SHIFT; + multiplier_mask = AR2313_CLOCKCTL1_MULTIPLIER_MASK; + multiplier_shift = AR2313_CLOCKCTL1_MULTIPLIER_SHIFT; + doubler_mask = AR2313_CLOCKCTL1_DOUBLER_MASK; + } else { /* AR5312 and AR2312 */ + predivide_mask = AR2312_CLOCKCTL1_PREDIVIDE_MASK; + predivide_shift = AR2312_CLOCKCTL1_PREDIVIDE_SHIFT; + multiplier_mask = AR2312_CLOCKCTL1_MULTIPLIER_MASK; + multiplier_shift = AR2312_CLOCKCTL1_MULTIPLIER_SHIFT; + doubler_mask = AR2312_CLOCKCTL1_DOUBLER_MASK; + } + + /* + * Clocking is derived from a fixed 40MHz input clock. + * + * cpuFreq = InputClock * MULT (where MULT is PLL multiplier) + * sysFreq = cpuFreq / 4 (used for APB clock, serial, + * flash, Timer, Watchdog Timer) + * + * cntFreq = cpuFreq / 2 (use for CPU count/compare) + * + * So, for example, with a PLL multiplier of 5, we have + * + * cpuFreq = 200MHz + * sysFreq = 50MHz + * cntFreq = 100MHz + * + * We compute the CPU frequency, based on PLL settings. + */ + + clock_ctl1 = __raw_readl((char *)KSEG1ADDR(AR2312_CLOCKCTL1)); + pre_divide_select = (clock_ctl1 & predivide_mask) >> predivide_shift; + pre_divisor = CLOCKCTL1_PREDIVIDE_TABLE[pre_divide_select]; + multiplier = (clock_ctl1 & multiplier_mask) >> multiplier_shift; + + if (clock_ctl1 & doubler_mask) + multiplier = multiplier << 1; + + return (40000000 / pre_divisor) * multiplier; +} + +static unsigned int +ar2312_sys_frequency(void) +{ + return ar2312_cpu_frequency() / 4; +} + +/* + * shutdown watchdog + */ +static int watchdog_init(void) +{ + pr_debug("Disable watchdog.\n"); + __raw_writeb(AR2312_WD_CTRL_IGNORE_EXPIRATION, + (char *)KSEG1ADDR(AR2312_WD_CTRL)); + return 0; +} + +static void flash_init(void) +{ + u32 ctl, old_ctl; + + /* Configure flash bank 0. + * Assume 8M maximum window size on this SoC. + * Flash will be aliased if it's smaller + */ + old_ctl = __raw_readl((char *)KSEG1ADDR(AR2312_FLASHCTL0)); + ctl = FLASHCTL_E | FLASHCTL_AC_8M | FLASHCTL_RBLE | + (0x01 << FLASHCTL_IDCY_S) | + (0x07 << FLASHCTL_WST1_S) | + (0x07 << FLASHCTL_WST2_S) | (old_ctl & FLASHCTL_MW); + + __raw_writel(ctl, (char *)KSEG1ADDR(AR2312_FLASHCTL0)); + /* Disable other flash banks */ + old_ctl = __raw_readl((char *)KSEG1ADDR(AR2312_FLASHCTL1)); + __raw_writel(old_ctl & ~(FLASHCTL_E | FLASHCTL_AC), + (char *)KSEG1ADDR(AR2312_FLASHCTL1)); + + old_ctl = __raw_readl((char *)KSEG1ADDR(AR2312_FLASHCTL2)); + __raw_writel(old_ctl & ~(FLASHCTL_E | FLASHCTL_AC), + (char *)KSEG1ADDR(AR2312_FLASHCTL2)); + + /* We need to find atheros config. MAC address is there. */ + ar231x_find_config((char *)KSEG1ADDR(AR2312_FLASH + + AR2312_MAX_FLASH_SIZE)); +} + +static int ether_init(void) +{ + static struct resource res[2]; + struct ar231x_eth_platform_data *eth = &ar231x_board.eth_pdata; + + /* Base ETH registers */ + res[0].start = KSEG1ADDR(AR2312_ENET1); + res[0].end = res[0].start + 0x100000 - 1; + res[0].flags = IORESOURCE_MEM; + /* Base PHY registers */ + res[1].start = KSEG1ADDR(AR2312_ENET0); + res[1].end = res[1].start + 0x100000 - 1; + res[1].flags = IORESOURCE_MEM; + + /* MAC address located in atheros config on flash. */ + eth->mac = ar231x_board.config->enet0_mac; + + eth->reset_mac = AR2312_RESET_ENET0 | AR2312_RESET_ENET1; + eth->reset_phy = AR2312_RESET_EPHY0 | AR2312_RESET_EPHY1; + + eth->reset_bit = ar231x_reset_bit; + + /* FIXME: base_reset should be replaced with reset driver */ + eth->base_reset = KSEG1ADDR(AR2312_RESET); + + add_generic_device_res("ar231x_eth", DEVICE_ID_DYNAMIC, res, 2, eth); + return 0; +} + +static int platform_init(void) +{ + add_generic_device("ar231x_reset", DEVICE_ID_SINGLE, NULL, + KSEG1ADDR(AR2312_RESET), 0x4, + IORESOURCE_MEM, NULL); + watchdog_init(); + flash_init(); + ether_init(); + return 0; +} +late_initcall(platform_init); + +static struct NS16550_plat serial_plat = { + .shift = AR2312_UART_SHIFT, +}; + +static int ar2312_console_init(void) +{ + u32 reset; + + /* reset UART0 */ + reset = __raw_readl((char *)KSEG1ADDR(AR2312_RESET)); + reset = ((reset & ~AR2312_RESET_APB) | AR2312_RESET_UART0); + __raw_writel(reset, (char *)KSEG1ADDR(AR2312_RESET)); + + reset &= ~AR2312_RESET_UART0; + __raw_writel(reset, (char *)KSEG1ADDR(AR2312_RESET)); + + /* Register the serial port */ + serial_plat.clock = ar2312_sys_frequency(); + add_ns16550_device(DEVICE_ID_DYNAMIC, KSEG1ADDR(AR2312_UART0), + 8 << AR2312_UART_SHIFT, IORESOURCE_MEM_8BIT, &serial_plat); + return 0; +} +console_initcall(ar2312_console_init); diff --git a/arch/mips/mach-ar231x/ar231x_reset.c b/arch/mips/mach-ar231x/ar231x_reset.c new file mode 100644 index 000000000..5ececb5c0 --- /dev/null +++ b/arch/mips/mach-ar231x/ar231x_reset.c @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2013 Oleksij Rempel + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include +#include +#include + +#include +#include + +static void __iomem *reset_base; + +void __noreturn reset_cpu(ulong addr) +{ + printf("reseting cpu\n"); + __raw_writel(0x10000, + (char *)KSEG1ADDR(AR2312_WD_TIMER)); + __raw_writel(AR2312_WD_CTRL_RESET, + (char *)KSEG1ADDR(AR2312_WD_CTRL)); + unreachable(); +} +EXPORT_SYMBOL(reset_cpu); + +static u32 ar231x_reset_readl(void) +{ + return __raw_readl(reset_base); +} + +static void ar231x_reset_writel(u32 val) +{ + __raw_writel(val, reset_base); +} + +void ar231x_reset_bit(u32 val, enum reset_state state) +{ + u32 tmp; + + tmp = ar231x_reset_readl(); + + if (state == REMOVE) + ar231x_reset_writel(tmp & ~val); + else + ar231x_reset_writel(tmp | val); +} +EXPORT_SYMBOL(ar231x_reset_bit); + +static int ar231x_reset_probe(struct device_d *dev) +{ + reset_base = dev_request_mem_region(dev, 0); + if (!reset_base) { + dev_err(dev, "could not get memory region\n"); + return -ENODEV; + } + + return 0; +} + +static struct driver_d ar231x_reset_driver = { + .probe = ar231x_reset_probe, + .name = "ar231x_reset", +}; + +static int ar231x_reset_init(void) +{ + return platform_driver_register(&ar231x_reset_driver); +} +coredevice_initcall(ar231x_reset_init); diff --git a/arch/mips/mach-ar231x/board.c b/arch/mips/mach-ar231x/board.c new file mode 100644 index 000000000..f1b876f76 --- /dev/null +++ b/arch/mips/mach-ar231x/board.c @@ -0,0 +1,188 @@ +/* + * Based on Linux driver: + * Copyright (C) 2003 Atheros Communications, Inc., All Rights Reserved. + * Copyright (C) 2006 FON Technology, SL. + * Copyright (C) 2006 Imre Kaloz + * Copyright (C) 2006-2009 Felix Fietkau + * Ported to Barebox: + * Copyright (C) 2013 Oleksij Rempel + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + + +#include +#include +#include +#include +#include +#include + +#define HDR_SIZE 6 + +#define TAB_1 "\t" +#define TAB_2 "\t\t" + +extern struct ar231x_board_data ar231x_board; + +static void +ar231x_print_mac(unsigned char *mac) +{ + int i; + for (i = 0; i < 5; i++) + printf("%02x:", mac[i]); + printf("%02x\n", mac[5]); +} + +#ifdef DEBUG_BOARD +static void +ar231x_print_board_config(struct ar231x_board_config *config) +{ + printf("board config:\n"); + printf(TAB_1 "chsum:" TAB_2 "%04x\n", config->cksum); + printf(TAB_1 "rev:" TAB_2 "%04x\n", config->rev); + printf(TAB_1 "name:" TAB_2 "%s\n", config->board_name); + printf(TAB_1 "maj:" TAB_2 "%04x\n", config->major); + printf(TAB_1 "min:" TAB_2 "%04x\n", config->minor); + printf(TAB_1 "board flags:" TAB_1 "%08x\n", config->flags); + + if (config->flags & BD_ENET0) + printf(TAB_2 "ENET0 is stuffed\n"); + if (config->flags & BD_ENET1) + printf(TAB_2 "ENET1 is stuffed\n"); + if (config->flags & BD_UART1) + printf(TAB_2 "UART1 is stuffed\n"); + if (config->flags & BD_UART0) + printf(TAB_2 "UART0 is stuffed (dma)\n"); + if (config->flags & BD_RSTFACTORY) + printf(TAB_2 "Reset factory defaults stuffed\n"); + if (config->flags & BD_SYSLED) + printf(TAB_2 "System LED stuffed\n"); + if (config->flags & BD_EXTUARTCLK) + printf(TAB_2 "External UART clock\n"); + if (config->flags & BD_CPUFREQ) + printf(TAB_2 "cpu freq is valid in nvram\n"); + if (config->flags & BD_SYSFREQ) + printf(TAB_2 "sys freq is set in nvram\n"); + if (config->flags & BD_WLAN0) + printf(TAB_2 "Enable WLAN0\n"); + if (config->flags & BD_MEMCAP) + printf(TAB_2 "CAP SDRAM @ memCap for testing\n"); + if (config->flags & BD_DISWATCHDOG) + printf(TAB_2 "disable system watchdog\n"); + if (config->flags & BD_WLAN1) + printf(TAB_2 "Enable WLAN1 (ar5212)\n"); + if (config->flags & BD_ISCASPER) + printf(TAB_2 "FLAG for AR2312\n"); + if (config->flags & BD_WLAN0_2G_EN) + printf(TAB_2 "FLAG for radio0_2G\n"); + if (config->flags & BD_WLAN0_5G_EN) + printf(TAB_2 "FLAG for radio0_5G\n"); + if (config->flags & BD_WLAN1_2G_EN) + printf(TAB_2 "FLAG for radio1_2G\n"); + if (config->flags & BD_WLAN1_5G_EN) + printf(TAB_2 "FLAG for radio1_5G\n"); + + printf(TAB_1 "ResetConf GPIO pin:" TAB_1 "%04x\n", + config->reset_config_gpio); + printf(TAB_1 "Sys LED GPIO pin:" TAB_1 "%04x\n", config->sys_led_gpio); + printf(TAB_1 "CPU Freq:" TAB_2 "%u\n", config->cpu_freq); + printf(TAB_1 "Sys Freq:" TAB_2 "%u\n", config->sys_freq); + printf(TAB_1 "Calculated Freq:" TAB_1 "%u\n", config->cnt_freq); + + printf(TAB_1 "wlan0 mac:" TAB_2); + ar231x_print_mac(config->wlan0_mac); + printf(TAB_1 "wlan1 mac:" TAB_2); + ar231x_print_mac(config->wlan1_mac); + printf(TAB_1 "eth0 mac:" TAB_2); + ar231x_print_mac(config->enet0_mac); + printf(TAB_1 "eth1 mac:" TAB_2); + ar231x_print_mac(config->enet1_mac); + + printf(TAB_1 "Pseudo PCIID:" TAB_2 "%04x\n", config->pci_id); + printf(TAB_1 "Mem capacity:" TAB_2 "%u\n", config->mem_cap); +} +#endif + +static u16 +ar231x_cksum16(u8 *data, int size) +{ + int i; + u16 sum; + + for (i = 0; i < size; i++) + sum += data[i]; + + return sum; +} + +static void +ar231x_check_mac(u8 *addr) +{ + if (!is_valid_ether_addr(addr)) { + pr_warn("config: no valid mac was found. " + "Generating random mac: "); + random_ether_addr(addr); + ar231x_print_mac(addr); + } +} + +static u8 * +ar231x_find_board_config(u8 *flash_limit) +{ + u8 *addr; + int found = 0; + + for (addr = flash_limit - 0x1000; + addr >= flash_limit - 0x30000; + addr -= 0x1000) { + + if (*((u32 *)addr) == AR231X_BD_MAGIC) { + found = 1; + pr_debug("config at %x\n", addr); + break; + } + } + + if (!found) + addr = NULL; + + return addr; +} + +void +ar231x_find_config(u8 *flash_limit) +{ + struct ar231x_board_config *config; + u8 *bcfg, bsize; + u8 brocken; + + bcfg = ar231x_find_board_config(flash_limit); + + bsize = sizeof(struct ar231x_board_config); + config = xzalloc(bsize); + ar231x_board.config = config; + + if (bcfg) { + u16 cksum; + /* Copy the board and radio data to RAM. + * If flash will go to CFI mode, we won't + * be able to read to from mapped memory area */ + memcpy(config, bcfg, bsize); + cksum = 0xca + ar231x_cksum16((unsigned char *)config + HDR_SIZE, + sizeof(struct ar231x_board_config) - HDR_SIZE); + if (cksum != config->cksum) { + pr_err("config: checksum is invalid: %04x != %04x\n", + cksum, config->cksum); + brocken = 1; + } + /* ar231x_print_board_config(config); */ + } + + /* We do not care about wlans here */ + ar231x_check_mac(config->enet0_mac); + ar231x_check_mac(config->enet1_mac); +} diff --git a/arch/mips/mach-ar231x/include/mach/ar2312_regs.h b/arch/mips/mach-ar231x/include/mach/ar2312_regs.h new file mode 100644 index 000000000..7ac1b09b9 --- /dev/null +++ b/arch/mips/mach-ar231x/include/mach/ar2312_regs.h @@ -0,0 +1,302 @@ +/* + * Based on Linux driver: + * Copyright (C) 2003 Atheros Communications, Inc., All Rights Reserved. + * Copyright (C) 2006 Imre Kaloz + * Copyright (C) 2006-2009 Felix Fietkau + * Ported to Barebox: + * Copyright (C) 2013 Oleksij Rempel + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#ifndef AR2312_H +#define AR2312_H + +#include + +/* Address Map */ +#define AR2312_SDRAM0 0x00000000 +#define AR2312_SDRAM1 0x08000000 +#define AR2312_WLAN0 0x18000000 +#define AR2312_WLAN1 0x18500000 +#define AR2312_ENET0 0x18100000 +#define AR2312_ENET1 0x18200000 +#define AR2312_SDRAMCTL 0x18300000 +#define AR2312_FLASHCTL 0x18400000 +#define AR2312_APBBASE 0x1c000000 +#define AR2312_FLASH 0x1e000000 + +#define AR2312_CPU_CLOCK_RATE 180000000 +/* Used by romSizeMemory to set SDRAM Memory Refresh */ +#define AR2312_SDRAM_CLOCK_RATE (AR2312_CPU_CLOCK_RATE / 2) +/* + * SDRAM Memory Refresh (MEM_REF) value is computed as: + * 15.625us * SDRAM_CLOCK_RATE (in MHZ) + */ +#define DESIRED_MEMORY_REFRESH_NSECS 15625 +#define AR2312_SDRAM_MEMORY_REFRESH_VALUE \ + ((DESIRED_MEMORY_REFRESH_NSECS * AR2312_SDRAM_CLOCK_RATE/1000000) / 1000) + +/* + * APB Address Map + */ +#define AR2312_UART0 (AR2312_APBBASE + 0x0003) /* high speed uart */ +#define AR2312_UART_SHIFT 2 +#define AR2312_UART1 (AR2312_APBBASE + 0x1000) /* ar2312 only */ +#define AR2312_GPIO (AR2312_APBBASE + 0x2000) +#define AR2312_RESETTMR (AR2312_APBBASE + 0x3000) +#define AR2312_APB2AHB (AR2312_APBBASE + 0x4000) + +/* + * AR2312_NUM_ENET_MAC defines the number of ethernet MACs that + * should be considered available. The AR2312 supports 2 enet MACS, + * even though many reference boards only actually use 1 of them + * (i.e. Only MAC 0 is actually connected to an enet PHY or PHY switch. + * The AR2312 supports 1 enet MAC. + */ +#define AR2312_NUM_ENET_MAC 2 + +/* + * Need these defines to determine true number of ethernet MACs + */ +#define AR5212_AR2312_REV2 0x52 /* AR2312 WMAC (AP31) */ +#define AR5212_AR2312_REV7 0x57 /* AR2312 WMAC (AP30-040) */ +#define AR5212_AR2313_REV8 0x58 /* AR2313 WMAC (AP43-030) */ + +/* Reset/Timer Block Address Map */ +#define AR2312_RESETTMR (AR2312_APBBASE + 0x3000) +#define AR2312_TIMER (AR2312_RESETTMR + 0x0000) /* countdown timer */ +#define AR2312_WD_CTRL (AR2312_RESETTMR + 0x0008) /* watchdog cntrl */ +#define AR2312_WD_TIMER (AR2312_RESETTMR + 0x000c) /* watchdog timer */ +#define AR2312_ISR (AR2312_RESETTMR + 0x0010) /* Intr Status Reg */ +#define AR2312_IMR (AR2312_RESETTMR + 0x0014) /* Intr Mask Reg */ +#define AR2312_RESET (AR2312_RESETTMR + 0x0020) +#define AR2312_CLOCKCTL0 (AR2312_RESETTMR + 0x0060) +#define AR2312_CLOCKCTL1 (AR2312_RESETTMR + 0x0064) +#define AR2312_CLOCKCTL2 (AR2312_RESETTMR + 0x0068) +#define AR2312_SCRATCH (AR2312_RESETTMR + 0x006c) +#define AR2312_PROCADDR (AR2312_RESETTMR + 0x0070) +#define AR2312_PROC1 (AR2312_RESETTMR + 0x0074) +#define AR2312_DMAADDR (AR2312_RESETTMR + 0x0078) +#define AR2312_DMA1 (AR2312_RESETTMR + 0x007c) +#define AR2312_ENABLE (AR2312_RESETTMR + 0x0080) /* interface enb */ +#define AR2312_REV (AR2312_RESETTMR + 0x0090) /* revision */ + +/* AR2312_WD_CTRL register bit field definitions */ +#define AR2312_WD_CTRL_IGNORE_EXPIRATION 0x0000 +#define AR2312_WD_CTRL_NMI 0x0001 +#define AR2312_WD_CTRL_RESET 0x0002 + +/* AR2312_ISR register bit field definitions */ +#define AR2312_ISR_NONE 0x0000 +#define AR2312_ISR_TIMER 0x0001 +#define AR2312_ISR_AHBPROC 0x0002 +#define AR2312_ISR_AHBDMA 0x0004 +#define AR2312_ISR_GPIO 0x0008 +#define AR2312_ISR_UART0 0x0010 +#define AR2312_ISR_UART0DMA 0x0020 +#define AR2312_ISR_WD 0x0040 +#define AR2312_ISR_LOCAL 0x0080 + +/* AR2312_RESET register bit field definitions */ +#define AR2312_RESET_SYSTEM 0x00000001 /* cold reset full system */ +#define AR2312_RESET_PROC 0x00000002 /* cold reset MIPS core */ +#define AR2312_RESET_WLAN0 0x00000004 /* cold reset WLAN MAC and BB */ +#define AR2312_RESET_EPHY0 0x00000008 /* cold reset ENET0 phy */ +#define AR2312_RESET_EPHY1 0x00000010 /* cold reset ENET1 phy */ +#define AR2312_RESET_ENET0 0x00000020 /* cold reset ENET0 mac */ +#define AR2312_RESET_ENET1 0x00000040 /* cold reset ENET1 mac */ +#define AR2312_RESET_UART0 0x00000100 /* cold reset UART0 (high speed) */ +#define AR2312_RESET_WLAN1 0x00000200 /* cold reset WLAN MAC/BB */ +#define AR2312_RESET_APB 0x00000400 /* cold reset APB (ar2312) */ +#define AR2312_RESET_WARM_PROC 0x00001000 /* warm reset MIPS core */ +#define AR2312_RESET_WARM_WLAN0_MAC 0x00002000 /* warm reset WLAN0 MAC */ +#define AR2312_RESET_WARM_WLAN0_BB 0x00004000 /* warm reset WLAN0 BaseBand */ +#define AR2312_RESET_NMI 0x00010000 /* send an NMI to the processor */ +#define AR2312_RESET_WARM_WLAN1_MAC 0x00020000 /* warm reset WLAN1 mac */ +#define AR2312_RESET_WARM_WLAN1_BB 0x00040000 /* warm reset WLAN1 baseband */ +#define AR2312_RESET_LOCAL_BUS 0x00080000 /* reset local bus */ +#define AR2312_RESET_WDOG 0x00100000 /* last reset was a watchdog */ + +/* Values for AR2312_CLOCKCTL1 + * + * The AR2312_CLOCKCTL1 register is loaded based on the speed of + * our incoming clock. Currently, all valid configurations + * for an AR2312 use an ar5112 radio clocked at 40MHz. Until + * there are other configurations available, we'll hardcode + * this 40MHz assumption. + */ +#define AR2312_INPUT_CLOCK 40000000 +#define AR2312_CLOCKCTL1_IN40_OUT160MHZ 0x0405 /* 40MHz in, 160Mhz out */ +#define AR2312_CLOCKCTL1_IN40_OUT180MHZ 0x0915 /* 40MHz in, 180Mhz out */ +#define AR2312_CLOCKCTL1_IN40_OUT200MHZ 0x1935 /* 40MHz in, 200Mhz out */ +#define AR2312_CLOCKCTL1_IN40_OUT220MHZ 0x0b15 /* 40MHz in, 220Mhz out */ +#define AR2312_CLOCKCTL1_IN40_OUT240MHZ 0x0605 /* 40MHz in, 240Mhz out */ + +#define AR2312_CLOCKCTL1_SELECTION AR2312_CLOCKCTL1_IN40_OUT180MHZ +#define AR2312_CPU_CLOCK_RATE 180000000 + +/* + * Special values for AR2313 'VIPER' PLL. + * + * These values do not match the latest datasheet for the AR2313, + * which appears to be an exact copy of the AR2312 in this area. + * The values were derived from the ECOS code provided in the Atheros + * LSDK-1.0 (and confirmed by checking values on an AR2313 reference + * design). + */ +#define AR2313_CLOCKCTL1_SELECTION 0x91245 + +/* Bit fields for AR2312_CLOCKCTL2 */ +#define AR2312_CLOCKCTL2_WANT_RESET 0x00000001 /* reset with new vals */ +#define AR2312_CLOCKCTL2_WANT_DIV2 0x00000010 /* request /2 clock */ +#define AR2312_CLOCKCTL2_WANT_DIV4 0x00000020 /* request /4 clock */ +#define AR2312_CLOCKCTL2_WANT_PLL_BYPASS 0x00000080 /* request PLL bypass */ +#define AR2312_CLOCKCTL2_STATUS_DIV2 0x10000000 /* have /2 clock */ +#define AR2312_CLOCKCTL2_STATUS_DIV4 0x20000000 /* have /4 clock */ +#define AR2312_CLOCKCTL2_STATUS_PLL_BYPASS 0x80000000 /* PLL is bypassed */ + +/* AR2312_CLOCKCTL1 register bit field definitions */ +#define AR2312_CLOCKCTL1_PREDIVIDE_MASK 0x00000030 +#define AR2312_CLOCKCTL1_PREDIVIDE_SHIFT 4 +#define AR2312_CLOCKCTL1_MULTIPLIER_MASK 0x00001f00 +#define AR2312_CLOCKCTL1_MULTIPLIER_SHIFT 8 +#define AR2312_CLOCKCTL1_DOUBLER_MASK 0x00010000 + +/* Valid for AR2313 */ +#define AR2313_CLOCKCTL1_PREDIVIDE_MASK 0x00003000 +#define AR2313_CLOCKCTL1_PREDIVIDE_SHIFT 12 +#define AR2313_CLOCKCTL1_MULTIPLIER_MASK 0x001f0000 +#define AR2313_CLOCKCTL1_MULTIPLIER_SHIFT 16 +#define AR2313_CLOCKCTL1_DOUBLER_MASK 0x00000000 + +/* Values for AR2312_CLOCKCTL */ +#define AR2312_CLOCKCTL_ETH0 0x0004 /* enable eth0 clock */ +#define AR2312_CLOCKCTL_ETH1 0x0008 /* enable eth1 clock */ +#define AR2312_CLOCKCTL_UART0 0x0010 /* enable UART0 external clock */ + + +/* AR2312_ENABLE register bit field definitions */ +#define AR2312_ENABLE_ENET0 0x0002 +#define AR2312_ENABLE_ENET1 0x0004 + +/* AR2312_REV register bit field definitions */ +#define AR2312_REV_WMAC_MAJ 0xf000 +#define AR2312_REV_WMAC_MAJ_S 12 +#define AR2312_REV_WMAC_MIN 0x0f00 +#define AR2312_REV_WMAC_MIN_S 8 +#define AR2312_REV_MAJ 0x00f0 +#define AR2312_REV_MAJ_S 4 +#define AR2312_REV_MIN 0x000f +#define AR2312_REV_MIN_S 0 +#define AR2312_REV_CHIP (AR2312_REV_MAJ|AR2312_REV_MIN) + +/* Major revision numbers, bits 7..4 of Revision ID register */ +#define AR2312_REV_MAJ_AR2312 0x4 +#define AR2312_REV_MAJ_AR2313 0x5 + +/* Minor revision numbers, bits 3..0 of Revision ID register */ +#define AR2312_REV_MIN_DUAL 0x0 /* Dual WLAN version */ +#define AR2312_REV_MIN_SINGLE 0x1 /* Single WLAN version */ + +/* AR2312_FLASHCTL register bit field definitions */ +#define FLASHCTL_IDCY 0x0000000f /* Idle cycle turn around time */ +#define FLASHCTL_IDCY_S 0 +#define FLASHCTL_WST1 0x000003e0 /* Wait state 1 */ +#define FLASHCTL_WST1_S 5 +#define FLASHCTL_RBLE 0x00000400 /* Read byte lane enable */ +#define FLASHCTL_WST2 0x0000f800 /* Wait state 2 */ +#define FLASHCTL_WST2_S 11 +#define FLASHCTL_AC 0x00070000 /* Flash address check (added) */ +#define FLASHCTL_AC_S 16 +#define FLASHCTL_AC_128K 0x00000000 +#define FLASHCTL_AC_256K 0x00010000 +#define FLASHCTL_AC_512K 0x00020000 +#define FLASHCTL_AC_1M 0x00030000 +#define FLASHCTL_AC_2M 0x00040000 +#define FLASHCTL_AC_4M 0x00050000 +#define FLASHCTL_AC_8M 0x00060000 +#define FLASHCTL_AC_RES 0x00070000 /* 16MB is not supported */ +#define FLASHCTL_E 0x00080000 /* Flash bank enable (added) */ +#define FLASHCTL_BUSERR 0x01000000 /* Bus transfer error status flag */ +#define FLASHCTL_WPERR 0x02000000 /* Write protect error status flag */ +#define FLASHCTL_WP 0x04000000 /* Write protect */ +#define FLASHCTL_BM 0x08000000 /* Burst mode */ +#define FLASHCTL_MW 0x30000000 /* Memory width */ +#define FLASHCTL_MWx8 0x00000000 /* Memory width x8 */ +#define FLASHCTL_MWx16 0x10000000 /* Memory width x16 */ +#define FLASHCTL_MWx32 0x20000000 /* Memory width x32 (not supported) */ +#define FLASHCTL_ATNR 0x00000000 /* Access type == no retry */ +#define FLASHCTL_ATR 0x80000000 /* Access type == retry every */ +#define FLASHCTL_ATR4 0xc0000000 /* Access type == retry every 4 */ + +#define AR2312_MAX_FLASH_SIZE 0x800000 + +/* ARM Flash Controller -- 3 flash banks with either x8 or x16 devices. */ +#define AR2312_FLASHCTL0 (AR2312_FLASHCTL + 0x00) +#define AR2312_FLASHCTL1 (AR2312_FLASHCTL + 0x04) +#define AR2312_FLASHCTL2 (AR2312_FLASHCTL + 0x08) + +/* ARM SDRAM Controller -- just enough to determine memory size */ +#define AR2312_MEM_CFG0 (AR2312_SDRAMCTL + 0x00) +#define AR2312_MEM_CFG1 (AR2312_SDRAMCTL + 0x04) +#define AR2312_MEM_REF (AR2312_SDRAMCTL + 0x08) /* 16 bit value */ + +#define MEM_CFG0_F0 0x00000002 /* bank 0: 256Mb support */ +#define MEM_CFG0_T0 0x00000004 /* bank 0: chip width */ +#define MEM_CFG0_B0 0x00000008 /* bank 0: 2 vs 4 bank */ +#define MEM_CFG0_F1 0x00000020 /* bank 1: 256Mb support */ +#define MEM_CFG0_T1 0x00000040 /* bank 1: chip width */ +#define MEM_CFG0_B1 0x00000080 /* bank 1: 2 vs 4 bank */ + /* bank 2 and 3 are not supported */ +#define MEM_CFG0_E 0x00020000 /* SDRAM clock control */ +#define MEM_CFG0_C 0x00040000 /* SDRAM clock enable */ +#define MEM_CFG0_X 0x00080000 /* bus width (0 == 32b) */ +#define MEM_CFG0_CAS 0x00300000 /* CAS latency (1-3) */ +#define MEM_CFG0_C1 0x00100000 +#define MEM_CFG0_C2 0x00200000 +#define MEM_CFG0_C3 0x00300000 +#define MEM_CFG0_R 0x00c00000 /* RAS to CAS latency (1-3) */ +#define MEM_CFG0_R1 0x00400000 +#define MEM_CFG0_R2 0x00800000 +#define MEM_CFG0_R3 0x00c00000 +#define MEM_CFG0_A 0x01000000 /* AHB auto pre-charge */ + +#define MEM_CFG1_I 0x0001 /* memory init control */ +#define MEM_CFG1_M 0x0002 /* memory init control */ +#define MEM_CFG1_R 0x0004 /* read buffer enable (unused) */ +#define MEM_CFG1_W 0x0008 /* write buffer enable (unused) */ +#define MEM_CFG1_B 0x0010 /* SDRAM engine busy */ +#define MEM_CFG1_AC_2 0 /* AC of 2MB */ +#define MEM_CFG1_AC_4 1 /* AC of 4MB */ +#define MEM_CFG1_AC_8 2 /* AC of 8MB */ +#define MEM_CFG1_AC_16 3 /* AC of 16MB */ +#define MEM_CFG1_AC_32 4 /* AC of 32MB */ +#define MEM_CFG1_AC_64 5 /* AC of 64MB */ +#define MEM_CFG1_AC_128 6 /* AC of 128MB */ + +#define MEM_CFG1_AC0_S 8 +#define MEM_CFG1_AC0 0x0700 /* bank 0: SDRAM addr check (added) */ +#define MEM_CFG1_E0 0x0800 /* bank 0: enable */ +#define MEM_CFG1_AC1_S 12 +#define MEM_CFG1_AC1 0x7000 /* bank 1: SDRAM addr check (added) */ +#define MEM_CFG1_E1 0x8000 /* bank 1: enable */ + +/* GPIO Address Map */ +#define AR2312_GPIO (AR2312_APBBASE + 0x2000) +#define AR2312_GPIO_DO (AR2312_GPIO + 0x00) /* output register */ +#define AR2312_GPIO_DI (AR2312_GPIO + 0x04) /* intput register */ +#define AR2312_GPIO_CR (AR2312_GPIO + 0x08) /* control register */ + +/* GPIO Control Register bit field definitions */ +#define AR2312_GPIO_CR_M(x) (1 << (x)) /* mask for i/o */ +#define AR2312_GPIO_CR_O(x) (0 << (x)) /* mask for output */ +#define AR2312_GPIO_CR_I(x) (1 << (x)) /* mask for input */ +#define AR2312_GPIO_CR_INT(x) (1 << ((x)+8)) /* mask for interrupt */ +#define AR2312_GPIO_CR_UART(x) (1 << ((x)+16)) /* uart multiplex */ +#define AR2312_NUM_GPIO 8 + +#endif diff --git a/arch/mips/mach-ar231x/include/mach/ar231x_platform.h b/arch/mips/mach-ar231x/include/mach/ar231x_platform.h new file mode 100644 index 000000000..18f55b69c --- /dev/null +++ b/arch/mips/mach-ar231x/include/mach/ar231x_platform.h @@ -0,0 +1,104 @@ +/* + * Based on Linux driver: + * Copyright (C) 2003 Atheros Communications, Inc., All Rights Reserved. + * Copyright (C) 2006 FON Technology, SL. + * Copyright (C) 2006 Imre Kaloz + * Copyright (C) 2006-2009 Felix Fietkau + * Ported to Barebox: + * Copyright (C) 2013 Oleksij Rempel + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#ifndef __AR231X_PLATFORM_H +#define __AR231X_PLATFORM_H + +/* + * This is board-specific data that is stored in a "fixed" location in flash. + * It is shared across operating systems, so it should not be changed lightly. + * The main reason we need it is in order to extract the ethernet MAC + * address(es). + */ +struct ar231x_board_config { + u32 magic; /* board data is valid */ +#define AR231X_BD_MAGIC 0x35333131 /* "5311", for all 531x platforms */ + u16 cksum; /* checksum (starting with BD_REV 2) */ + u16 rev; /* revision of this struct */ +#define BD_REV 4 + char boardName[64]; /* Name of board */ + u16 major; /* Board major number */ + u16 minor; /* Board minor number */ + u32 flags; /* Board configuration */ +#define BD_ENET0 0x00000001 /* ENET0 is stuffed */ +#define BD_ENET1 0x00000002 /* ENET1 is stuffed */ +#define BD_UART1 0x00000004 /* UART1 is stuffed */ +#define BD_UART0 0x00000008 /* UART0 is stuffed (dma) */ +#define BD_RSTFACTORY 0x00000010 /* Reset factory defaults stuffed */ +#define BD_SYSLED 0x00000020 /* System LED stuffed */ +#define BD_EXTUARTCLK 0x00000040 /* External UART clock */ +#define BD_CPUFREQ 0x00000080 /* cpu freq is valid in nvram */ +#define BD_SYSFREQ 0x00000100 /* sys freq is set in nvram */ +#define BD_WLAN0 0x00000200 /* Enable WLAN0 */ +#define BD_MEMCAP 0x00000400 /* CAP SDRAM @ memCap for testing */ +#define BD_DISWATCHDOG 0x00000800 /* disable system watchdog */ +#define BD_WLAN1 0x00001000 /* Enable WLAN1 (ar5212) */ +#define BD_ISCASPER 0x00002000 /* FLAG for AR2312 */ +#define BD_WLAN0_2G_EN 0x00004000 /* FLAG for radio0_2G */ +#define BD_WLAN0_5G_EN 0x00008000 /* FLAG for radio0_2G */ +#define BD_WLAN1_2G_EN 0x00020000 /* FLAG for radio0_2G */ +#define BD_WLAN1_5G_EN 0x00040000 /* FLAG for radio0_2G */ + u16 resetConfigGpio; /* Reset factory GPIO pin */ + u16 sysLedGpio; /* System LED GPIO pin */ + + u32 cpuFreq; /* CPU core frequency in Hz */ + u32 sysFreq; /* System frequency in Hz */ + u32 cntFreq; /* Calculated C0_COUNT frequency */ + + u8 wlan0_mac[6]; + u8 enet0_mac[6]; + u8 enet1_mac[6]; + + u16 pciId; /* Pseudo PCIID for common code */ + u16 memCap; /* cap bank1 in MB */ + + /* version 3 */ + u8 wlan1_mac[6]; /* (ar5212) */ +}; + +#define BOARD_CONFIG_BUFSZ 0x1000 + +/* + * Platform device information for the Ethernet MAC + */ +enum reset_state { + SET, + REMOVE, +}; + +struct ar231x_eth_platform_data { + u32 base_reset; + u32 reset_mac; + u32 reset_phy; + + u8 *mac; + + void (*reset_bit)(u32 val, enum reset_state state); +}; + +struct ar231x_board_data { + u16 devid; + + /* board config data */ + struct ar231x_board_config *config; + + struct ar231x_eth_platform_data eth_pdata; +}; + +void ar231x_find_config(u8 *flash_limit); + +void ar231x_reset_bit(u32 val, enum reset_state state); + +#endif /* __AR231X_PLATFORM_H */ From 7d27f0db932d2a584409a3c5c85a229638597e65 Mon Sep 17 00:00:00 2001 From: Oleksij Rempel Date: Thu, 30 May 2013 20:18:41 +0200 Subject: [PATCH 12/15] net: add ar231x-eth support This driver should work with some Atheros WiSoCs: - ar2312, ar2313 - ar2315, ar2316 ... Signed-off-by: Oleksij Rempel Signed-off-by: Sascha Hauer --- drivers/net/Kconfig | 7 + drivers/net/Makefile | 1 + drivers/net/ar231x.c | 437 +++++++++++++++++++++++++++++++++++++++++++ drivers/net/ar231x.h | 219 ++++++++++++++++++++++ 4 files changed, 664 insertions(+) create mode 100644 drivers/net/ar231x.c create mode 100644 drivers/net/ar231x.h diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 2736094b8..5ad3e4d46 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -27,6 +27,13 @@ menu "Network drivers" source "drivers/net/phy/Kconfig" +config DRIVER_NET_AR231X + bool "AR231X Ethernet support" + depends on MACH_MIPS_AR231X + select PHYLIB + help + Support for the AR231x/531x ethernet controller + config DRIVER_NET_CALXEDA_XGMAC bool "Calxeda xgmac" diff --git a/drivers/net/Makefile b/drivers/net/Makefile index 42136f87c..73403fecf 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -1,3 +1,4 @@ +obj-$(CONFIG_DRIVER_NET_AR231X) += ar231x.o obj-$(CONFIG_DRIVER_NET_CALXEDA_XGMAC) += xgmac.o obj-$(CONFIG_DRIVER_NET_CS8900) += cs8900.o obj-$(CONFIG_DRIVER_NET_CPSW) += cpsw.o diff --git a/drivers/net/ar231x.c b/drivers/net/ar231x.c new file mode 100644 index 000000000..5c091140a --- /dev/null +++ b/drivers/net/ar231x.c @@ -0,0 +1,437 @@ +/* + * ar231x.c: driver for the Atheros AR231x Ethernet device. + * This device is build in to SoC on ar231x series. + * All known of them are big endian. + * + * Based on Linux driver: + * Copyright (C) 2004 by Sameer Dekate + * Copyright (C) 2006 Imre Kaloz + * Copyright (C) 2006-2009 Felix Fietkau + * Ported to Barebox: + * Copyright (C) 2013 Oleksij Rempel + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ +/* + * Known issues: + * - broadcast packets are not filtered by hardware. On noisy network with + * lots of bcast packages rx_buffer can be completely filled after. Currently + * we clear rx_buffer transmit some package. + */ + +#include +#include +#include +#include + +#include "ar231x.h" + +static inline void dma_writel(struct ar231x_eth_priv *priv, + u32 val, int reg) +{ + __raw_writel(val, priv->dma_regs + reg); +} + +static inline u32 dma_readl(struct ar231x_eth_priv *priv, int reg) +{ + return __raw_readl(priv->dma_regs + reg); +} + +static inline void eth_writel(struct ar231x_eth_priv *priv, + u32 val, int reg) +{ + __raw_writel(val, priv->eth_regs + reg); +} + +static inline u32 eth_readl(struct ar231x_eth_priv *priv, int reg) +{ + return __raw_readl(priv->eth_regs + reg); +} + +static inline void phy_writel(struct ar231x_eth_priv *priv, + u32 val, int reg) +{ + __raw_writel(val, priv->phy_regs + reg); +} + +static inline u32 phy_readl(struct ar231x_eth_priv *priv, int reg) +{ + return __raw_readl(priv->phy_regs + reg); +} + +static void ar231x_reset_bit_(struct ar231x_eth_priv *priv, + u32 val, enum reset_state state) +{ + if (priv->reset_bit) + (*priv->reset_bit)(val, state); +} + +static int ar231x_set_ethaddr(struct eth_device *edev, unsigned char *addr); +static void ar231x_reset_regs(struct eth_device *edev) +{ + struct ar231x_eth_priv *priv = edev->priv; + struct ar231x_eth_platform_data *cfg = priv->cfg; + u32 flags; + + ar231x_reset_bit_(priv, cfg->reset_mac, SET); + mdelay(10); + + ar231x_reset_bit_(priv, cfg->reset_mac, REMOVE); + mdelay(10); + + ar231x_reset_bit_(priv, cfg->reset_phy, SET); + mdelay(10); + + ar231x_reset_bit_(priv, cfg->reset_phy, REMOVE); + mdelay(10); + + dma_writel(priv, DMA_BUS_MODE_SWR, AR231X_DMA_BUS_MODE); + mdelay(10); + + dma_writel(priv, ((32 << DMA_BUS_MODE_PBL_SHIFT) | DMA_BUS_MODE_BLE), + AR231X_DMA_BUS_MODE); + + /* FIXME: priv->{t,r}x_ring are virtual addresses, + * use virt-to-phys convertion */ + dma_writel(priv, (u32)priv->tx_ring, AR231X_DMA_TX_RING); + dma_writel(priv, (u32)priv->rx_ring, AR231X_DMA_RX_RING); + + dma_writel(priv, (DMA_CONTROL_SR | DMA_CONTROL_ST | DMA_CONTROL_SF), + AR231X_DMA_CONTROL); + + eth_writel(priv, FLOW_CONTROL_FCE, AR231X_ETH_FLOW_CONTROL); + /* TODO: not sure if we need it here. */ + eth_writel(priv, 0x8100, AR231X_ETH_VLAN_TAG); + + /* Enable Ethernet Interface */ + flags = (MAC_CONTROL_TE | /* transmit enable */ + /* FIXME: MAC_CONTROL_PM - pass mcast. + * Seems like it makes no difference on some WiSoCs, + * for example ar2313. + * It should be tested on ar231[5,6,7] */ + MAC_CONTROL_PM | + MAC_CONTROL_F | /* full duplex */ + MAC_CONTROL_HBD); /* heart beat disabled */ + eth_writel(priv, flags, AR231X_ETH_MAC_CONTROL); +} + +static void ar231x_flash_rxdsc(struct ar231x_descr *rxdsc) +{ + rxdsc->status = DMA_RX_OWN; + rxdsc->devcs = ((AR2313_RX_BUFSIZE << DMA_RX1_BSIZE_SHIFT) | + DMA_RX1_CHAINED); +} + +static void ar231x_allocate_dma_descriptors(struct eth_device *edev) +{ + struct ar231x_eth_priv *priv = edev->priv; + u16 ar231x_descr_size = sizeof(struct ar231x_descr); + u16 i; + + priv->tx_ring = xmalloc(ar231x_descr_size); + dev_dbg(&edev->dev, "allocate tx_ring @ %p\n", priv->tx_ring); + + priv->rx_ring = xmalloc(ar231x_descr_size * AR2313_RXDSC_ENTRIES); + dev_dbg(&edev->dev, "allocate rx_ring @ %p\n", priv->rx_ring); + + priv->rx_buffer = xmalloc(AR2313_RX_BUFSIZE * AR2313_RXDSC_ENTRIES); + dev_dbg(&edev->dev, "allocate rx_buffer @ %p\n", priv->rx_buffer); + + /* Initialize the rx Descriptors */ + for (i = 0; i < AR2313_RXDSC_ENTRIES; i++) { + struct ar231x_descr *rxdsc = &priv->rx_ring[i]; + ar231x_flash_rxdsc(rxdsc); + rxdsc->buffer_ptr = + (u32)(priv->rx_buffer + AR2313_RX_BUFSIZE * i); + rxdsc->next_dsc_ptr = (u32)&priv->rx_ring[DSC_NEXT(i)]; + } + /* set initial position of ring descriptor */ + priv->next_rxdsc = &priv->rx_ring[0]; +} + +static void ar231x_adjust_link(struct eth_device *edev) +{ + struct ar231x_eth_priv *priv = edev->priv; + u32 mc; + + if (edev->phydev->duplex != priv->oldduplex) { + mc = eth_readl(priv, AR231X_ETH_MAC_CONTROL); + mc &= ~(MAC_CONTROL_F | MAC_CONTROL_DRO); + if (edev->phydev->duplex) + mc |= MAC_CONTROL_F; + else + mc |= MAC_CONTROL_DRO; + eth_writel(priv, mc, AR231X_ETH_MAC_CONTROL); + priv->oldduplex = edev->phydev->duplex; + } +} + +static int ar231x_eth_init(struct eth_device *edev) +{ + struct ar231x_eth_priv *priv = edev->priv; + + ar231x_allocate_dma_descriptors(edev); + ar231x_reset_regs(edev); + ar231x_set_ethaddr(edev, priv->mac); + return 0; +} + +static int ar231x_eth_open(struct eth_device *edev) +{ + struct ar231x_eth_priv *priv = edev->priv; + u32 tmp; + + /* Enable RX. Now the rx_buffer will be filled. + * If it is full we may lose first transmission. In this case + * barebox should retry it. + * Or TODO: - force HW to filter some how broadcasts + * - disable RX if we do not need it. */ + tmp = eth_readl(priv, AR231X_ETH_MAC_CONTROL); + eth_writel(priv, (tmp | MAC_CONTROL_RE), AR231X_ETH_MAC_CONTROL); + + return phy_device_connect(edev, &priv->miibus, (int)priv->phy_regs, + ar231x_adjust_link, 0, PHY_INTERFACE_MODE_MII); +} + +static int ar231x_eth_recv(struct eth_device *edev) +{ + struct ar231x_eth_priv *priv = edev->priv; + + while (1) { + struct ar231x_descr *rxdsc = priv->next_rxdsc; + u32 status = rxdsc->status; + + /* owned by DMA? */ + if (status & DMA_RX_OWN) + break; + + /* Pick only packets what we can handle: + * - only complete packet per buffer + * (First and Last at same time) + * - drop multicast */ + if (!priv->kill_rx_ring && + ((status & DMA_RX_MASK) == DMA_RX_FSLS)) { + u16 length = + ((status >> DMA_RX_LEN_SHIFT) & 0x3fff) + - CRC_LEN; + net_receive((void *)rxdsc->buffer_ptr, length); + } + /* Clean descriptor. now it is owned by DMA. */ + priv->next_rxdsc = (struct ar231x_descr *)rxdsc->next_dsc_ptr; + ar231x_flash_rxdsc(rxdsc); + } + priv->kill_rx_ring = 0; + return 0; +} + +static int ar231x_eth_send(struct eth_device *edev, void *packet, + int length) +{ + struct ar231x_eth_priv *priv = edev->priv; + struct ar231x_descr *txdsc = priv->tx_ring; + u32 rx_missed; + + /* We do not do async work. + * If rx_ring is full, there is nothing we can use. */ + rx_missed = dma_readl(priv, AR231X_DMA_RX_MISSED); + if (rx_missed) { + priv->kill_rx_ring = 1; + ar231x_eth_recv(edev); + } + + /* Setup the transmit descriptor. */ + txdsc->devcs = ((length << DMA_TX1_BSIZE_SHIFT) | DMA_TX1_DEFAULT); + txdsc->buffer_ptr = (uint)packet; + txdsc->status = DMA_TX_OWN; + + /* Trigger transmission */ + dma_writel(priv, 0, AR231X_DMA_TX_POLL); + + /* Take enough time to transmit packet. 100 is not enough. */ + wait_on_timeout(2000 * MSECOND, + !(txdsc->status & DMA_TX_OWN)); + + /* We can't do match here. If it is still in progress, + * then engine is probably stalled or we wait not enough. */ + if (txdsc->status & DMA_TX_OWN) + dev_err(&edev->dev, "Frame is still in progress.\n"); + + if (txdsc->status & DMA_TX_ERROR) + dev_err(&edev->dev, "Frame was aborted by engine\n"); + + /* Ready or not. Stop it. */ + txdsc->status = 0; + return 0; +} + +static void ar231x_eth_halt(struct eth_device *edev) +{ + struct ar231x_eth_priv *priv = edev->priv; + u32 tmp; + + /* kill the MAC: disable RX and TX */ + tmp = eth_readl(priv, AR231X_ETH_MAC_CONTROL); + eth_writel(priv, tmp & ~(MAC_CONTROL_RE | MAC_CONTROL_TE), + AR231X_ETH_MAC_CONTROL); + + /* stop DMA */ + dma_writel(priv, 0, AR231X_DMA_CONTROL); + dma_writel(priv, DMA_BUS_MODE_SWR, AR231X_DMA_BUS_MODE); + + /* place PHY and MAC in reset */ + ar231x_reset_bit_(priv, (priv->cfg->reset_mac | priv->cfg->reset_phy), SET); +} + +static int ar231x_get_ethaddr(struct eth_device *edev, unsigned char *addr) +{ + struct ar231x_eth_priv *priv = edev->priv; + + /* MAC address is stored on flash, in some kind of atheros config + * area. Platform code should read it and pass to the driver. */ + memcpy(addr, priv->mac, 6); + return 0; +} + +/** + * These device do not have build in MAC address. + * It is located on atheros-config field on flash. + */ +static int ar231x_set_ethaddr(struct eth_device *edev, unsigned char *addr) +{ + struct ar231x_eth_priv *priv = edev->priv; + + eth_writel(priv, + (addr[5] << 8) | (addr[4]), + AR231X_ETH_MAC_ADDR1); + eth_writel(priv, + (addr[3] << 24) | (addr[2] << 16) | + (addr[1] << 8) | addr[0], + AR231X_ETH_MAC_ADDR2); + + mdelay(10); + return 0; +} + +#define MII_ADDR(phy, reg) \ + ((reg << MII_ADDR_REG_SHIFT) | (phy << MII_ADDR_PHY_SHIFT)) + +static int ar231x_miibus_read(struct mii_bus *bus, int phy_id, int regnum) +{ + struct ar231x_eth_priv *priv = bus->priv; + uint64_t time_start; + + phy_writel(priv, MII_ADDR(phy_id, regnum), AR231X_ETH_MII_ADDR); + time_start = get_time_ns(); + while (phy_readl(priv, AR231X_ETH_MII_ADDR) & MII_ADDR_BUSY) { + if (is_timeout(time_start, SECOND)) { + dev_err(&bus->dev, "miibus read timeout\n"); + return -ETIMEDOUT; + } + } + return phy_readl(priv, AR231X_ETH_MII_DATA) >> MII_DATA_SHIFT; +} + +static int ar231x_miibus_write(struct mii_bus *bus, int phy_id, + int regnum, u16 val) +{ + struct ar231x_eth_priv *priv = bus->priv; + uint64_t time_start = get_time_ns(); + + while (phy_readl(priv, AR231X_ETH_MII_ADDR) & MII_ADDR_BUSY) { + if (is_timeout(time_start, SECOND)) { + dev_err(&bus->dev, "miibus write timeout\n"); + return -ETIMEDOUT; + } + } + phy_writel(priv, val << MII_DATA_SHIFT, AR231X_ETH_MII_DATA); + phy_writel(priv, MII_ADDR(phy_id, regnum) | MII_ADDR_WRITE, + AR231X_ETH_MII_ADDR); + return 0; +} + +static int ar231x_mdiibus_reset(struct mii_bus *bus) +{ + struct ar231x_eth_priv *priv = bus->priv; + + ar231x_reset_regs(&priv->edev); + return 0; +} + +static int ar231x_eth_probe(struct device_d *dev) +{ + struct ar231x_eth_priv *priv; + struct eth_device *edev; + struct mii_bus *miibus; + struct ar231x_eth_platform_data *pdata; + + if (!dev->platform_data) { + dev_err(dev, "no platform data\n"); + return -ENODEV; + } + + pdata = dev->platform_data; + + priv = xzalloc(sizeof(struct ar231x_eth_priv)); + edev = &priv->edev; + miibus = &priv->miibus; + edev->priv = priv; + + /* link all platform depended regs */ + priv->mac = pdata->mac; + priv->reset_bit = pdata->reset_bit; + + priv->eth_regs = dev_request_mem_region(dev, 0); + if (priv->eth_regs == NULL) { + dev_err(dev, "No eth_regs!!\n"); + return -ENODEV; + } + /* we have 0x100000 for eth, part of it are dma regs. + * So they are already requested */ + priv->dma_regs = (void *)(priv->eth_regs + 0x1000); + + priv->phy_regs = dev_request_mem_region(dev, 1); + if (priv->phy_regs == NULL) { + dev_err(dev, "No phy_regs!!\n"); + return -ENODEV; + } + + priv->cfg = pdata; + edev->init = ar231x_eth_init; + edev->open = ar231x_eth_open; + edev->send = ar231x_eth_send; + edev->recv = ar231x_eth_recv; + edev->halt = ar231x_eth_halt; + edev->get_ethaddr = ar231x_get_ethaddr; + edev->set_ethaddr = ar231x_set_ethaddr; + + priv->miibus.read = ar231x_miibus_read; + priv->miibus.write = ar231x_miibus_write; + priv->miibus.reset = ar231x_mdiibus_reset; + priv->miibus.priv = priv; + priv->miibus.parent = dev; + + mdiobus_register(miibus); + eth_register(edev); + + return 0; +} + +static void ar231x_eth_remove(struct device_d *dev) +{ + +} + +static struct driver_d ar231x_eth_driver = { + .name = "ar231x_eth", + .probe = ar231x_eth_probe, + .remove = ar231x_eth_remove, +}; + +static int ar231x_eth_driver_init(void) +{ + return platform_driver_register(&ar231x_eth_driver); +} +device_initcall(ar231x_eth_driver_init); diff --git a/drivers/net/ar231x.h b/drivers/net/ar231x.h new file mode 100644 index 000000000..24684127c --- /dev/null +++ b/drivers/net/ar231x.h @@ -0,0 +1,219 @@ +/* + * ar231x.h: Linux driver for the Atheros AR231x Ethernet device. + * Based on Linux driver: + * Copyright (C) 2004 by Sameer Dekate + * Copyright (C) 2006 Imre Kaloz + * Copyright (C) 2006-2009 Felix Fietkau + * Ported to Barebox: + * Copyright (C) 2013 Oleksij Rempel + * + * Thanks to Atheros for providing hardware and documentation + * enabling me to write this driver. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#ifndef _AR2313_2_H_ +#define _AR2313_2_H_ + +#include +#include + +/* Allocate 64 RX buffers. This will reduce packet loss, until we will start + * processing them. It is important in noisy network with lots of broadcasts. */ +#define AR2313_RXDSC_ENTRIES 64 +#define DSC_NEXT(idx) (((idx) + 1) & (AR2313_RXDSC_ENTRIES - 1)) + +/* Use system default buffers size. At the moment of writing it was 1518 */ +#define AR2313_RX_BUFSIZE PKTSIZE +#define CRC_LEN 4 + +/** + * DMA controller + */ +#define AR231X_DMA_BUS_MODE 0x00 /* (CSR0) */ +#define AR231X_DMA_TX_POLL 0x04 /* (CSR1) */ +#define AR231X_DMA_RX_POLL 0x08 /* (CSR2) */ +#define AR231X_DMA_RX_RING 0x0c /* (CSR3) */ +#define AR231X_DMA_TX_RING 0x10 /* (CSR4) */ +#define AR231X_DMA_STATUS 0x14 /* (CSR5) */ +#define AR231X_DMA_CONTROL 0x18 /* (CSR6) */ +#define AR231X_DMA_INTR_ENA 0x1c /* (CSR7) */ +#define AR231X_DMA_RX_MISSED 0x20 /* (CSR8) */ +/* reserverd 0x24-0x4c (CSR9-19) */ +#define AR231X_DMA_CUR_TX_BUF_ADDR 0x50 /* (CSR20) */ +#define AR231X_DMA_CUR_RX_BUF_ADDR 0x54 /* (CSR21) */ + +/** + * Ethernet controller + */ +#define AR231X_ETH_MAC_CONTROL 0x00 +#define AR231X_ETH_MAC_ADDR1 0x04 +#define AR231X_ETH_MAC_ADDR2 0x08 +#define AR231X_ETH_MCAST_TABLE1 0x0c +#define AR231X_ETH_MCAST_TABLE2 0x10 +#define AR231X_ETH_MII_ADDR 0x14 +#define AR231X_ETH_MII_DATA 0x18 +#define AR231X_ETH_FLOW_CONTROL 0x1c +#define AR231X_ETH_VLAN_TAG 0x20 +/* pad 0x24 - 0x3c */ +/* ucast_table 0x40-0x5c */ + +/** + * RX descriptor status bits. ar231x_descr.status + */ +#define DMA_RX_ERR_CRC BIT(1) +#define DMA_RX_ERR_DRIB BIT(2) +#define DMA_RX_ERR_MII BIT(3) +#define DMA_RX_EV2 BIT(5) +#define DMA_RX_ERR_COL BIT(6) +#define DMA_RX_LONG BIT(7) +#define DMA_RX_LS BIT(8) /* last descriptor */ +#define DMA_RX_FS BIT(9) /* first descriptor */ +#define DMA_RX_MF BIT(10) /* multicast frame */ +#define DMA_RX_ERR_RUNT BIT(11) /* runt frame */ +#define DMA_RX_ERR_LENGTH BIT(12) /* length error */ +#define DMA_RX_ERR_DESC BIT(14) /* descriptor error */ +#define DMA_RX_ERROR BIT(15) /* error summary */ +#define DMA_RX_LEN_MASK 0x3fff0000 +#define DMA_RX_LEN_SHIFT 16 +#define DMA_RX_FILT BIT(30) +#define DMA_RX_OWN BIT(31) /* desc owned by DMA controller */ +#define DMA_RX_FSLS (DMA_RX_LS | DMA_RX_FS) +#define DMA_RX_MASK (DMA_RX_FSLS | DMA_RX_MF | DMA_RX_ERROR) + +/** + * RX descriptor configuration bits. ar231x_descr.devcs + */ +#define DMA_RX1_BSIZE_MASK 0x000007ff +#define DMA_RX1_BSIZE_SHIFT 0 +#define DMA_RX1_CHAINED BIT(24) +#define DMA_RX1_RER BIT(25) + +/** + * TX descriptor status fields. ar231x_descr.status + */ +#define DMA_TX_ERR_UNDER BIT(1) /* underflow error */ +#define DMA_TX_ERR_DEFER BIT(2) /* excessive deferral */ +#define DMA_TX_COL_MASK 0x78 +#define DMA_TX_COL_SHIFT 3 +#define DMA_TX_ERR_HB BIT(7) /* hearbeat failure */ +#define DMA_TX_ERR_COL BIT(8) /* excessive collisions */ +#define DMA_TX_ERR_LATE BIT(9) /* late collision */ +#define DMA_TX_ERR_LINK BIT(10) /* no carrier */ +#define DMA_TX_ERR_LOSS BIT(11) /* loss of carrier */ +#define DMA_TX_ERR_JABBER BIT(14) /* transmit jabber timeout */ +#define DMA_TX_ERROR BIT(15) /* frame aborted */ +#define DMA_TX_OWN BIT(31) /* descr owned by DMA controller */ + +/** + * TX descriptor configuration bits. ar231x_descr.devcs + */ +#define DMA_TX1_BSIZE_MASK 0x000007ff +#define DMA_TX1_BSIZE_SHIFT 0 +#define DMA_TX1_CHAINED BIT(24) /* chained descriptors */ +#define DMA_TX1_TER BIT(25) /* transmit end of ring */ +#define DMA_TX1_FS BIT(29) /* first segment */ +#define DMA_TX1_LS BIT(30) /* last segment */ +#define DMA_TX1_IC BIT(31) /* interrupt on completion */ +#define DMA_TX1_DEFAULT (DMA_TX1_FS | DMA_TX1_LS | DMA_TX1_TER) + +#define MAC_CONTROL_RE BIT(2) /* receive enable */ +#define MAC_CONTROL_TE BIT(3) /* transmit enable */ +#define MAC_CONTROL_DC BIT(5) /* Deferral check */ +#define MAC_CONTROL_ASTP BIT(8) /* Auto pad strip */ +#define MAC_CONTROL_DRTY BIT(10) /* Disable retry */ +#define MAC_CONTROL_DBF BIT(11) /* Disable bcast frames */ +#define MAC_CONTROL_LCC BIT(12) /* late collision ctrl */ +#define MAC_CONTROL_HP BIT(13) /* Hash Perfect filtering */ +#define MAC_CONTROL_HASH BIT(14) /* Unicast hash filtering */ +#define MAC_CONTROL_HO BIT(15) /* Hash only filtering */ +#define MAC_CONTROL_PB BIT(16) /* Pass Bad frames */ +#define MAC_CONTROL_IF BIT(17) /* Inverse filtering */ +#define MAC_CONTROL_PR BIT(18) /* promiscuous mode + * (valid frames only) */ +#define MAC_CONTROL_PM BIT(19) /* pass multicast */ +#define MAC_CONTROL_F BIT(20) /* full-duplex */ +#define MAC_CONTROL_DRO BIT(23) /* Disable Receive Own */ +#define MAC_CONTROL_HBD BIT(28) /* heart-beat disabled (MUST BE SET) */ +#define MAC_CONTROL_BLE BIT(30) /* big endian mode */ +#define MAC_CONTROL_RA BIT(31) /* receive all + * (valid and invalid frames) */ + +#define MII_ADDR_BUSY BIT(0) +#define MII_ADDR_WRITE BIT(1) +#define MII_ADDR_REG_SHIFT 6 +#define MII_ADDR_PHY_SHIFT 11 +#define MII_DATA_SHIFT 0 + +#define FLOW_CONTROL_FCE BIT(1) + +#define DMA_BUS_MODE_SWR BIT(0) /* software reset */ +#define DMA_BUS_MODE_BLE BIT(7) /* big endian mode */ +#define DMA_BUS_MODE_PBL_SHIFT 8 /* programmable burst length 32 */ +#define DMA_BUS_MODE_DBO BIT(20) /* big-endian descriptors */ + +#define DMA_STATUS_TI BIT(0) /* transmit interrupt */ +#define DMA_STATUS_TPS BIT(1) /* transmit process stopped */ +#define DMA_STATUS_TU BIT(2) /* transmit buffer unavailable */ +#define DMA_STATUS_TJT BIT(3) /* transmit buffer timeout */ +#define DMA_STATUS_UNF BIT(5) /* transmit underflow */ +#define DMA_STATUS_RI BIT(6) /* receive interrupt */ +#define DMA_STATUS_RU BIT(7) /* receive buffer unavailable */ +#define DMA_STATUS_RPS BIT(8) /* receive process stopped */ +#define DMA_STATUS_ETI BIT(10) /* early transmit interrupt */ +#define DMA_STATUS_FBE BIT(13) /* fatal bus interrupt */ +#define DMA_STATUS_ERI BIT(14) /* early receive interrupt */ +#define DMA_STATUS_AIS BIT(15) /* abnormal interrupt summary */ +#define DMA_STATUS_NIS BIT(16) /* normal interrupt summary */ +#define DMA_STATUS_RS_SHIFT 17 /* receive process state */ +#define DMA_STATUS_TS_SHIFT 20 /* transmit process state */ +#define DMA_STATUS_EB_SHIFT 23 /* error bits */ + +#define DMA_CONTROL_SR BIT(1) /* start receive */ +#define DMA_CONTROL_ST BIT(13) /* start transmit */ +#define DMA_CONTROL_SF BIT(21) /* store and forward */ + + +struct ar231x_descr { + u32 status; /* OWN, Device control and status. */ + u32 devcs; /* Packet control bitmap + Length. */ + u32 buffer_ptr; /* Pointer to packet buffer. */ + u32 next_dsc_ptr; /* Pointer to next descriptor in chain. */ +}; + +/** + * Struct private for the Sibyte. + * + * Elements are grouped so variables used by the tx handling goes + * together, and will go into the same cache lines etc. in order to + * avoid cache line contention between the rx and tx handling on SMP. + * + * Frequently accessed variables are put at the beginning of the + * struct to help the compiler generate better/shorter code. + */ +struct ar231x_eth_priv { + struct ar231x_eth_platform_data *cfg; + u8 *mac; + void __iomem *phy_regs; + void __iomem *eth_regs; + void __iomem *dma_regs; + void __iomem *reset_regs; + + struct eth_device edev; + struct mii_bus miibus; + + struct ar231x_descr *tx_ring; + struct ar231x_descr *rx_ring; + struct ar231x_descr *next_rxdsc; + u8 kill_rx_ring; + void *rx_buffer; + + int oldduplex; + void (*reset_bit)(u32 val, enum reset_state state); +}; + +#endif /* _AR2313_H_ */ From b993cc4a226c145368af1eeb44f3cc002fc0b676 Mon Sep 17 00:00:00 2001 From: Oleksij Rempel Date: Thu, 30 May 2013 20:18:42 +0200 Subject: [PATCH 13/15] MIPS: ar231x: add netgear-wg102 Signed-off-by: Antony Pavlov Signed-off-by: Oleksij Rempel Signed-off-by: Sascha Hauer --- arch/mips/Makefile | 1 + arch/mips/boards/netgear-wg102/Kconfig | 6 ++++++ arch/mips/boards/netgear-wg102/Makefile | 1 + arch/mips/boards/netgear-wg102/ram.c | 11 +++++++++++ arch/mips/mach-ar231x/Kconfig | 10 ++++++++++ 5 files changed, 29 insertions(+) create mode 100644 arch/mips/boards/netgear-wg102/Kconfig create mode 100644 arch/mips/boards/netgear-wg102/Makefile create mode 100644 arch/mips/boards/netgear-wg102/ram.c diff --git a/arch/mips/Makefile b/arch/mips/Makefile index 135259f4d..dc0fe56d6 100644 --- a/arch/mips/Makefile +++ b/arch/mips/Makefile @@ -73,6 +73,7 @@ machine-$(CONFIG_MACH_MIPS_MALTA) := malta board-$(CONFIG_BOARD_QEMU_MALTA) := qemu-malta machine-$(CONFIG_MACH_MIPS_AR231X) := ar231x +board-$(CONFIG_BOARD_NETGEAR_WG102) := netgear-wg102 machine-$(CONFIG_MACH_MIPS_BCM47XX) := bcm47xx board-$(CONFIG_BOARD_DLINK_DIR320) := dlink-dir-320 diff --git a/arch/mips/boards/netgear-wg102/Kconfig b/arch/mips/boards/netgear-wg102/Kconfig new file mode 100644 index 000000000..ceca6de82 --- /dev/null +++ b/arch/mips/boards/netgear-wg102/Kconfig @@ -0,0 +1,6 @@ +if BOARD_NETGEAR_WG102 + +config BOARDINFO + default "Netgear WG102" + +endif diff --git a/arch/mips/boards/netgear-wg102/Makefile b/arch/mips/boards/netgear-wg102/Makefile new file mode 100644 index 000000000..0899b66c5 --- /dev/null +++ b/arch/mips/boards/netgear-wg102/Makefile @@ -0,0 +1 @@ +obj-y += ram.o diff --git a/arch/mips/boards/netgear-wg102/ram.c b/arch/mips/boards/netgear-wg102/ram.c new file mode 100644 index 000000000..00a008a1e --- /dev/null +++ b/arch/mips/boards/netgear-wg102/ram.c @@ -0,0 +1,11 @@ +#include +#include +#include +#include + +static int mem_init(void) +{ + mips_add_ram0(SZ_16M); + return 0; +} +mem_initcall(mem_init); diff --git a/arch/mips/mach-ar231x/Kconfig b/arch/mips/mach-ar231x/Kconfig index 7694fe287..1c6a12f88 100644 --- a/arch/mips/mach-ar231x/Kconfig +++ b/arch/mips/mach-ar231x/Kconfig @@ -4,4 +4,14 @@ config ARCH_TEXT_BASE hex default 0xa0800000 +choice + prompt "Board type" + +config BOARD_NETGEAR_WG102 + bool "Netgear WG102" + +endchoice + +source arch/mips/boards/netgear-wg102/Kconfig + endif From 3c90cbfa64c04895c5dbed55b7712bfe9a375295 Mon Sep 17 00:00:00 2001 From: Antony Pavlov Date: Sat, 1 Jun 2013 11:52:44 +0400 Subject: [PATCH 14/15] MIPS: XBurst: use mach-specific debug_ll setup Ingenic JZ4755 SoC (JZ4750D family) has three UARTs. So we can give to the user choose which one of them to use for low level debug (debug_ll) output. Also this commit adapts the only JZ4755 board (Ritmix RZX50) for using the new debug_ll port selection. Signed-off-by: Antony Pavlov Signed-off-by: Sascha Hauer --- .../boards/rzx50/include/board/debug_ll.h | 5 +-- arch/mips/mach-xburst/Kconfig | 18 +++++++++ .../include/mach/debug_ll_jz4750d.h | 37 +++++++++++++++++++ .../mach-xburst/include/mach/jz4750d_regs.h | 2 + 4 files changed, 58 insertions(+), 4 deletions(-) create mode 100644 arch/mips/mach-xburst/include/mach/debug_ll_jz4750d.h diff --git a/arch/mips/boards/rzx50/include/board/debug_ll.h b/arch/mips/boards/rzx50/include/board/debug_ll.h index 3d183b0a1..7ae0e2a4f 100644 --- a/arch/mips/boards/rzx50/include/board/debug_ll.h +++ b/arch/mips/boards/rzx50/include/board/debug_ll.h @@ -18,9 +18,6 @@ #ifndef __INCLUDE_RZX50_BOARD_DEBUG_LL_H__ #define __INCLUDE_RZX50_BOARD_DEBUG_LL_H__ -#include - -#define DEBUG_LL_UART_ADDR UART1_BASE -#define DEBUG_LL_UART_SHIFT 2 +#include #endif /* __INCLUDE_RZX50_BOARD_DEBUG_LL_H__ */ diff --git a/arch/mips/mach-xburst/Kconfig b/arch/mips/mach-xburst/Kconfig index c72b7414d..e6413d563 100644 --- a/arch/mips/mach-xburst/Kconfig +++ b/arch/mips/mach-xburst/Kconfig @@ -17,6 +17,24 @@ config BOARD_RZX50 endchoice +if DEBUG_LL +if CPU_JZ4755 +choice + prompt "DEBUG_LL port" + +config JZ4750D_DEBUG_LL_UART0 + bool "UART0" + +config JZ4750D_DEBUG_LL_UART1 + bool "UART1" + +config JZ4750D_DEBUG_LL_UART2 + bool "UART2" + +endchoice +endif # CPU_JZ4755 +endif # DEBUG_LL + source arch/mips/boards/rzx50/Kconfig endif diff --git a/arch/mips/mach-xburst/include/mach/debug_ll_jz4750d.h b/arch/mips/mach-xburst/include/mach/debug_ll_jz4750d.h new file mode 100644 index 000000000..7bf66b12a --- /dev/null +++ b/arch/mips/mach-xburst/include/mach/debug_ll_jz4750d.h @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2013 Antony Pavlov + * + * This file is part of barebox. + * See file CREDITS for list of people who contributed to this project. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#ifndef __INCLUDE_DEBUG_LL_JZ4750D_H__ +#define __INCLUDE_DEBUG_LL_JZ4750D_H__ + +#include + +#ifdef CONFIG_JZ4750D_DEBUG_LL_UART0 +#define DEBUG_LL_UART_ADDR UART0_BASE +#endif + +#ifdef CONFIG_JZ4750D_DEBUG_LL_UART1 +#define DEBUG_LL_UART_ADDR UART1_BASE +#endif + +#ifdef CONFIG_JZ4750D_DEBUG_LL_UART2 +#define DEBUG_LL_UART_ADDR UART2_BASE +#endif + +#define DEBUG_LL_UART_SHIFT 2 + +#endif /* __INCLUDE_DEBUG_LL_JZ4750D_H__ */ diff --git a/arch/mips/mach-xburst/include/mach/jz4750d_regs.h b/arch/mips/mach-xburst/include/mach/jz4750d_regs.h index eafdd2fa7..7a3daadb1 100644 --- a/arch/mips/mach-xburst/include/mach/jz4750d_regs.h +++ b/arch/mips/mach-xburst/include/mach/jz4750d_regs.h @@ -16,7 +16,9 @@ #define TCU_BASE 0xb0002000 #define WDT_BASE 0xb0002000 #define RTC_BASE 0xb0003000 +#define UART0_BASE 0xb0030000 #define UART1_BASE 0xb0031000 +#define UART2_BASE 0xb0032000 /************************************************************************* * TCU (Timer Counter Unit) From 68d80258efd94515bd3927187d2dd4f2e188ae20 Mon Sep 17 00:00:00 2001 From: Antony Pavlov Date: Sat, 1 Jun 2013 11:52:45 +0400 Subject: [PATCH 15/15] MIPS: pbl: add low-level debug asm macros for ns16550 This patch adds macros for ns16550 port initialisation and single char output. The macros can be used in MIPS asm pbl code. Signed-off-by: Antony Pavlov Signed-off-by: Sascha Hauer --- arch/mips/include/asm/debug_ll_ns16550.h | 100 +++++++++++++++++++++++ 1 file changed, 100 insertions(+) create mode 100644 arch/mips/include/asm/debug_ll_ns16550.h diff --git a/arch/mips/include/asm/debug_ll_ns16550.h b/arch/mips/include/asm/debug_ll_ns16550.h new file mode 100644 index 000000000..5dd1b3904 --- /dev/null +++ b/arch/mips/include/asm/debug_ll_ns16550.h @@ -0,0 +1,100 @@ +/* + * Copyright (C) 2012, 2013 Antony Pavlov + * + * This file is part of barebox. + * See file CREDITS for list of people who contributed to this project. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +/** @file + * This file contains declaration for early output support + */ +#ifndef __INCLUDE_MIPS_ASM_DEBUG_LL_NS16550_H__ +#define __INCLUDE_MIPS_ASM_DEBUG_LL_NS16550_H__ + +#ifdef CONFIG_DEBUG_LL + +#ifndef DEBUG_LL_UART_ADDR +#error DEBUG_LL_UART_ADDR is undefined! +#endif + +#ifndef DEBUG_LL_UART_SHIFT +#error DEBUG_LL_UART_SHIFT is undefined! +#endif + +#ifndef DEBUG_LL_UART_DIVISOR +#error DEBUG_LL_UART_DIVISOR is undefined! +#endif + +#endif /* CONFIG_DEBUG_LL */ + +#define UART_THR (0x0 << DEBUG_LL_UART_SHIFT) +#define UART_DLL (0x0 << DEBUG_LL_UART_SHIFT) +#define UART_DLM (0x1 << DEBUG_LL_UART_SHIFT) +#define UART_LCR (0x3 << DEBUG_LL_UART_SHIFT) +#define UART_LSR (0x5 << DEBUG_LL_UART_SHIFT) + +#define UART_LCR_W 0x07 /* Set UART to 8,N,2 & DLAB = 0 */ +#define UART_LCR_DLAB 0x87 /* Set UART to 8,N,2 & DLAB = 1 */ + +#define UART_LSR_THRE 0x20 /* Xmit holding register empty */ + +/* + * Macros for use in assembly language code + */ + +.macro debug_ll_ns16550_init +#ifdef CONFIG_DEBUG_LL + la t0, DEBUG_LL_UART_ADDR + + li t1, UART_LCR_DLAB /* DLAB on */ + sb t1, UART_LCR(t0) /* Write it out */ + + li t1, DEBUG_LL_UART_DIVISOR + sb t1, UART_DLL(t0) /* write low order byte */ + srl t1, t1, 8 + sb t1, UART_DLM(t0) /* write high order byte */ + + li t1, UART_LCR_W /* DLAB off */ + sb t1, UART_LCR(t0) /* Write it out */ +#endif /* CONFIG_DEBUG_LL */ +.endm + +/* + * output a character in a0 + */ +.macro debug_ll_ns16550_outc chr +#ifdef CONFIG_DEBUG_LL + li a0, \chr + la t0, DEBUG_LL_UART_ADDR + +1: lbu t1, UART_LSR(t0) /* get line status */ + nop + andi t1, t1, UART_LSR_THRE /* check for transmitter empty */ + beqz t1, 1b /* try again */ + nop + + sb a0, UART_THR(t0) /* write the character */ +#endif /* CONFIG_DEBUG_LL */ +.endm + +/* + * output CR + NL + */ +.macro debug_ll_ns16550_outnl +#ifdef CONFIG_DEBUG_LL + debug_ll_ns16550_outc '\r' + debug_ll_ns16550_outc '\n' +#endif /* CONFIG_DEBUG_LL */ +.endm + +#endif /* __INCLUDE_MIPS_ASM_DEBUG_LL_NS16550_H__ */