mail archive of the barebox mailing list
 help / color / mirror / Atom feed
* [RFC, PATCH v2 0/3] work on atheros ar2313
@ 2013-05-22  7:49 Oleksij Rempel
  2013-05-22  7:49 ` [RFC, PATCH v2 1/3] MIPS: add Atheros ar531x family support Oleksij Rempel
                   ` (2 more replies)
  0 siblings, 3 replies; 10+ messages in thread
From: Oleksij Rempel @ 2013-05-22  7:49 UTC (permalink / raw)
  To: barebox

Hello all,
here is next version of pachtes for atheros ar2313.
Previous comments was handled and some more work was done

Oleksij Rempel (3):
  MIPS: add Atheros ar531x family support
  net: add ar231x-eth support
  MIPS: ar231x: add netgear-wg102

 arch/mips/Kconfig                                  |  10 +
 arch/mips/Makefile                                 |   3 +
 arch/mips/boards/netgear-wg102/Kconfig             |   6 +
 arch/mips/boards/netgear-wg102/Makefile            |   1 +
 arch/mips/boards/netgear-wg102/ram.c               |  13 +
 arch/mips/mach-ar231x/Kconfig                      |  17 +
 arch/mips/mach-ar231x/Makefile                     |   3 +
 arch/mips/mach-ar231x/ar231x.c                     | 199 ++++++++++
 arch/mips/mach-ar231x/ar231x_reset.c               |  64 +++
 arch/mips/mach-ar231x/board.c                      | 184 +++++++++
 arch/mips/mach-ar231x/include/mach/ar2312_regs.h   | 269 +++++++++++++
 .../mach-ar231x/include/mach/ar231x_platform.h     |  89 +++++
 arch/mips/mach-ar231x/include/mach/debug_ll.h      |  35 ++
 drivers/net/Kconfig                                |   7 +
 drivers/net/Makefile                               |   1 +
 drivers/net/ar231x.c                               | 429 +++++++++++++++++++++
 drivers/net/ar231x.h                               | 219 +++++++++++
 17 files changed, 1549 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
 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
 create mode 100644 arch/mips/mach-ar231x/include/mach/debug_ll.h
 create mode 100644 drivers/net/ar231x.c
 create mode 100644 drivers/net/ar231x.h

-- 
1.8.1.2


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [RFC, PATCH v2 1/3] MIPS: add Atheros ar531x family support
  2013-05-22  7:49 [RFC, PATCH v2 0/3] work on atheros ar2313 Oleksij Rempel
@ 2013-05-22  7:49 ` Oleksij Rempel
  2013-05-23 13:35   ` Sascha Hauer
  2013-05-22  7:49 ` [RFC, PATCH v2 2/3] net: add ar231x-eth support Oleksij Rempel
  2013-05-22  7:49 ` [RFC, PATCH v2 3/3] MIPS: ar231x: add netgear-wg102 Oleksij Rempel
  2 siblings, 1 reply; 10+ messages in thread
From: Oleksij Rempel @ 2013-05-22  7:49 UTC (permalink / raw)
  To: barebox

Signed-off-by: Oleksij Rempel <linux@rempel-privat.de>
Signed-off-by: Antony Pavlov <antonynpavlov@gmail.com>
---
 arch/mips/Kconfig                                  |  10 +
 arch/mips/Makefile                                 |   2 +
 arch/mips/mach-ar231x/Kconfig                      |   7 +
 arch/mips/mach-ar231x/Makefile                     |   3 +
 arch/mips/mach-ar231x/ar231x.c                     | 199 +++++++++++++++
 arch/mips/mach-ar231x/ar231x_reset.c               |  64 +++++
 arch/mips/mach-ar231x/board.c                      | 184 ++++++++++++++
 arch/mips/mach-ar231x/include/mach/ar2312_regs.h   | 269 +++++++++++++++++++++
 .../mach-ar231x/include/mach/ar231x_platform.h     |  89 +++++++
 arch/mips/mach-ar231x/include/mach/debug_ll.h      |  35 +++
 10 files changed, 862 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
 create mode 100644 arch/mips/mach-ar231x/include/mach/debug_ll.h

diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index d58b804..8d2a2ce 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -45,6 +45,15 @@ config MACH_MIPS_MALTA
 	select SYS_SUPPORTS_BIG_ENDIAN
 	select HAS_DEBUG_LL
 
+config MACH_MIPS_AR231X
+	bool "Atheros ar231x-based boards"
+	select CSRC_R4K_LIB
+	select DRIVER_SERIAL_NS16550
+	select SYS_HAS_CPU_MIPS32_R1
+	select SYS_SUPPORTS_32BIT_KERNEL
+	select SYS_SUPPORTS_BIG_ENDIAN
+	select HAS_DEBUG_LL
+
 config MACH_MIPS_BCM47XX
 	bool "Broadcom BCM47xx-based boards"
 	select CSRC_R4K_LIB
@@ -64,6 +73,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 c038933..135259f 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 0000000..7694fe2
--- /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 0000000..eba8e81
--- /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 0000000..d0add52
--- /dev/null
+++ b/arch/mips/mach-ar231x/ar231x.c
@@ -0,0 +1,199 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2003 Atheros Communications, Inc.,  All Rights Reserved.
+ * Copyright (C) 2006 FON Technology, SL.
+ * Copyright (C) 2006 Imre Kaloz <kaloz@openwrt.org>
+ * Copyright (C) 2006-2009 Felix Fietkau <nbd@openwrt.org>
+ */
+
+/*
+ * Platform devices for Atheros SoCs
+ */
+
+
+#include <common.h>
+#include <init.h>
+#include <io.h>
+#include <ns16550.h>
+#include <mach/ar231x_platform.h>
+#include <mach/debug_ll.h>
+
+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 clockCtl1, preDivideSelect, preDivisor, 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.
+	 */
+
+	clockCtl1 = __raw_readl((char *)KSEG1ADDR(AR2312_CLOCKCTL1));
+	preDivideSelect = (clockCtl1 & predivide_mask) >> predivide_shift;
+	preDivisor = CLOCKCTL1_PREDIVIDE_TABLE[preDivideSelect];
+	multiplier = (clockCtl1 & multiplier_mask) >> multiplier_shift;
+
+	if (clockCtl1 & doubler_mask) {
+		multiplier = multiplier << 1;
+	}
+	return (40000000 / preDivisor) * 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));
+	/* FIXME: currently we can't configure cfi flash. cfi driver is not able to
+	 * auto detect bus and flash width.
+	 */
+	add_cfi_flash_device(DEVICE_ID_SINGLE, KSEG1ADDR(AR2312_FLASH), 4 * 1024 * 1024, 0);
+}
+
+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_ENET1;
+	eth->reset_phy = AR2312_RESET_EPHY0;
+
+	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("ar2312_eth", DEVICE_ID_DYNAMIC, res, 2, eth);
+	return 0;
+}
+
+static int platform_init(void)
+{
+	add_generic_device("ar2312_reset", DEVICE_ID_SINGLE, NULL,
+			KSEG1ADDR(AR2312_RESETTMR), 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 0000000..6a9b070
--- /dev/null
+++ b/arch/mips/mach-ar231x/ar231x_reset.c
@@ -0,0 +1,64 @@
+#include <common.h>
+#include <init.h>
+#include <io.h>
+
+#include <mach/ar2312_regs.h>
+#include <mach/ar231x_platform.h>
+
+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 0000000..69ee882
--- /dev/null
+++ b/arch/mips/mach-ar231x/board.c
@@ -0,0 +1,184 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2003 Atheros Communications, Inc.,  All Rights Reserved.
+ * Copyright (C) 2006 FON Technology, SL.
+ * Copyright (C) 2006 Imre Kaloz <kaloz@openwrt.org>
+ * Copyright (C) 2006-2009 Felix Fietkau <nbd@openwrt.org>
+ * Copyright (C) 2013 Oleksij Rempel <linux@rempel-privat.de>
+ */
+
+#include <common.h>
+#include <io.h>
+#include <mach/ar2312_regs.h>
+#include <mach/ar231x_platform.h>
+// this is needed only by eclipse
+#include <linux/stddef.h>
+#include <net.h>
+
+#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->boardName);
+	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->resetConfigGpio);
+	printf(TAB_1 "Sys LED GPIO pin:" TAB_1 "%04x\n", config->sysLedGpio);
+	printf(TAB_1 "CPU Freq:" TAB_2 "%u\n", config->cpuFreq);
+	printf(TAB_1 "Sys Freq:" TAB_2 "%u\n", config->sysFreq);
+	printf(TAB_1 "Calculated Freq:" TAB_1 "%u\n", config->cntFreq);
+
+	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->pciId);
+	printf(TAB_1 "Mem capacity:" TAB_2 "%u\n", config->memCap);
+}
+#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, because accessing the mapped
+		 * memory of the flash directly after booting is not safe */
+		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 0000000..bc2f22d
--- /dev/null
+++ b/arch/mips/mach-ar231x/include/mach/ar2312_regs.h
@@ -0,0 +1,269 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2003 Atheros Communications, Inc.,  All Rights Reserved.
+ * Copyright (C) 2006 Imre Kaloz <kaloz@openwrt.org>
+ * Copyright (C) 2006 Felix Fietkau <nbd@openwrt.org>
+ */
+
+#ifndef AR2312_H
+#define AR2312_H
+
+#include <asm/addrspace.h>
+
+/* 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      0x0052          /* AR2312 WMAC (AP31) */
+#define AR5212_AR2312_REV7      0x0057          /* AR2312 WMAC (AP30-040) */
+#define AR5212_AR2313_REV8      0x0058          /* AR2313 WMAC (AP43-030) */
+
+/*
+ * AR2312_NUM_WMAC defines the number of Wireless MACs that\
+ * should be considered available.
+ */
+#define AR2312_NUM_WMAC                 2
+
+/* 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 */
+
+/* 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
+
+/* AR2312_ENABLE register bit field definitions */
+#define AR2312_ENABLE_WLAN0              0x0001
+#define AR2312_ENABLE_ENET0              0x0002
+#define AR2312_ENABLE_ENET1              0x0004
+#define AR2312_ENABLE_UART_AND_WLAN1_PIO 0x0008   /* UART, and WLAN1 PIOs */
+#define AR2312_ENABLE_WLAN1_DMA          0x0010   /* WLAN1 DMAs */
+#define AR2312_ENABLE_WLAN1 \
+            (AR2312_ENABLE_UART_AND_WLAN1_PIO | AR2312_ENABLE_WLAN1_DMA)
+
+/* 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_CFG1_AC0    0x00000700      /* bank 0: SDRAM addr check (added) */
+#define MEM_CFG1_AC0_S  8
+#define MEM_CFG1_AC1    0x00007000      /* bank 1: SDRAM addr check (added) */
+#define MEM_CFG1_AC1_S  12
+
+#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      0x00000001      /* memory init control */
+#define MEM_CFG1_M      0x00000002      /* memory init control */
+#define MEM_CFG1_R      0x00000004      /* read buffer enable (unused) */
+#define MEM_CFG1_W      0x00000008      /* write buffer enable (unused) */
+#define MEM_CFG1_B      0x00000010      /* SDRAM engine busy */
+#define MEM_CFG1_AC0    0x00000700      /* bank 0: SDRAM addr check (added) */
+#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_E0     0x00000800      /* bank 0: enable */
+#define MEM_CFG1_AC1    0x00007000      /* bank 1: SDRAM addr check (added) */
+#define MEM_CFG1_AC1_S  12
+#define MEM_CFG1_E1     0x00008000      /* 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 0000000..9784879
--- /dev/null
+++ b/arch/mips/mach-ar231x/include/mach/ar231x_platform.h
@@ -0,0 +1,89 @@
+#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 */
diff --git a/arch/mips/mach-ar231x/include/mach/debug_ll.h b/arch/mips/mach-ar231x/include/mach/debug_ll.h
new file mode 100644
index 0000000..92da40f
--- /dev/null
+++ b/arch/mips/mach-ar231x/include/mach/debug_ll.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2011 Antony Pavlov <antonynpavlov@gmail.com>
+ *
+ * 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 __MACH_AR231X_DEBUG_LL_H__
+#define __MACH_AR231X_DEBUG_LL_H__
+
+#include <mach/ar2312_regs.h>
+
+#define DEBUG_LL_UART_ADDR	KSEG1ADDR(AR2312_UART0)
+#define DEBUG_LL_UART_SHIFT	AR2312_UART_SHIFT
+
+#define DEBUG_LL_UART_CLK	(45000000 / 16)
+#define DEBUG_LL_UART_BPS	CONFIG_BAUDRATE
+#define DEBUG_LL_UART_DIVISOR	(DEBUG_LL_UART_CLK / DEBUG_LL_UART_BPS)
+
+#include <debug_ll_ns16550.h>
+
+#endif  /* __MACH_AR231X_DEBUG_LL_H__ */
-- 
1.8.1.2


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [RFC, PATCH v2 2/3] net: add ar231x-eth support
  2013-05-22  7:49 [RFC, PATCH v2 0/3] work on atheros ar2313 Oleksij Rempel
  2013-05-22  7:49 ` [RFC, PATCH v2 1/3] MIPS: add Atheros ar531x family support Oleksij Rempel
@ 2013-05-22  7:49 ` Oleksij Rempel
  2013-05-24  7:09   ` Sascha Hauer
  2013-05-22  7:49 ` [RFC, PATCH v2 3/3] MIPS: ar231x: add netgear-wg102 Oleksij Rempel
  2 siblings, 1 reply; 10+ messages in thread
From: Oleksij Rempel @ 2013-05-22  7:49 UTC (permalink / raw)
  To: barebox

This driver should work with some Atheros WiSoCs:
- ar2312, ar2313
- ar2315, ar2316 ...

Signed-off-by: Oleksij Rempel <linux@rempel-privat.de>
---
 drivers/net/Kconfig  |   7 +
 drivers/net/Makefile |   1 +
 drivers/net/ar231x.c | 429 +++++++++++++++++++++++++++++++++++++++++++++++++++
 drivers/net/ar231x.h | 219 ++++++++++++++++++++++++++
 4 files changed, 656 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 2736094..5ad3e4d 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 42136f8..73403fe 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 0000000..e7c0da7
--- /dev/null
+++ b/drivers/net/ar231x.c
@@ -0,0 +1,429 @@
+/*
+ * 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 <sdekate@arubanetworks.com>
+ *   Copyright (C) 2006 Imre Kaloz <kaloz@openwrt.org>
+ *   Copyright (C) 2006-2009 Felix Fietkau <nbd@openwrt.org>
+ * Ported to Barebox:
+ *   Copyright (C) 2013 Oleksij Rempel <linux@rempel-privat.de>
+ *
+ * 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 <common.h>
+#include <net.h>
+#include <init.h>
+#include <io.h>
+
+#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->eth_regs = dev_request_mem_region(dev, 0);
+	/* 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);
+
+	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 0000000..2468412
--- /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 <sdekate@arubanetworks.com>
+ *		Copyright (C) 2006 Imre Kaloz <kaloz@openwrt.org>
+ *		Copyright (C) 2006-2009 Felix Fietkau <nbd@openwrt.org>
+ * Ported to Barebox:
+ *		Copyright (C) 2013 Oleksij Rempel <linux@rempel-privat.de>
+ *
+ * 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 <net.h>
+#include <mach/ar231x_platform.h>
+
+/* 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_ */
-- 
1.8.1.2


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [RFC, PATCH v2 3/3] MIPS: ar231x: add netgear-wg102
  2013-05-22  7:49 [RFC, PATCH v2 0/3] work on atheros ar2313 Oleksij Rempel
  2013-05-22  7:49 ` [RFC, PATCH v2 1/3] MIPS: add Atheros ar531x family support Oleksij Rempel
  2013-05-22  7:49 ` [RFC, PATCH v2 2/3] net: add ar231x-eth support Oleksij Rempel
@ 2013-05-22  7:49 ` Oleksij Rempel
  2 siblings, 0 replies; 10+ messages in thread
From: Oleksij Rempel @ 2013-05-22  7:49 UTC (permalink / raw)
  To: barebox

Signed-off-by: Antony Pavlov <antonynpavlov@gmail.com>
Signed-off-by: Oleksij Rempel <linux@rempel-privat.de>
---
 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    | 13 +++++++++++++
 arch/mips/mach-ar231x/Kconfig           | 10 ++++++++++
 5 files changed, 31 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 135259f..dc0fe56 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 0000000..ceca6de
--- /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 0000000..0899b66
--- /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 0000000..43beb52
--- /dev/null
+++ b/arch/mips/boards/netgear-wg102/ram.c
@@ -0,0 +1,13 @@
+#include <common.h>
+#include <init.h>
+#include <sizes.h>
+#include <asm/memory.h>
+
+static int mem_init(void)
+{
+	/* FIXME: theoretically we can calculate ram size */
+	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 7694fe2..1c6a12f 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
-- 
1.8.1.2


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [RFC, PATCH v2 1/3] MIPS: add Atheros ar531x family support
  2013-05-22  7:49 ` [RFC, PATCH v2 1/3] MIPS: add Atheros ar531x family support Oleksij Rempel
@ 2013-05-23 13:35   ` Sascha Hauer
  2013-05-23 13:43     ` Oleksij Rempel
  0 siblings, 1 reply; 10+ messages in thread
From: Sascha Hauer @ 2013-05-23 13:35 UTC (permalink / raw)
  To: Oleksij Rempel; +Cc: barebox

Hi Oleksij,

On Wed, May 22, 2013 at 09:49:47AM +0200, Oleksij Rempel wrote:
> Signed-off-by: Oleksij Rempel <linux@rempel-privat.de>
> Signed-off-by: Antony Pavlov <antonynpavlov@gmail.com>
> +
> +/*
> + * 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 clockCtl1, preDivideSelect, preDivisor, multiplier;

No CamelCase please.

> +static int platform_init(void)
> +{
> +	add_generic_device("ar2312_reset", DEVICE_ID_SINGLE, NULL,
> +			KSEG1ADDR(AR2312_RESETTMR), 0x4,
> +			IORESOURCE_MEM, NULL);
> +	watchdog_init();
> +	flash_init();
> +	ether_init();

Whether or not the flash/ethernet/serial device is available is board
specific, not SoC specific, so this should be done in board code. It's
good to provide helpers to make this simple for the board code though,
so a good option would be to add a SoC prefix to the functions and call
it from board code.

Otherwise I am fine with this patch, but maybe Antony still has some
comments.

Sascha

-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [RFC, PATCH v2 1/3] MIPS: add Atheros ar531x family support
  2013-05-23 13:35   ` Sascha Hauer
@ 2013-05-23 13:43     ` Oleksij Rempel
  0 siblings, 0 replies; 10+ messages in thread
From: Oleksij Rempel @ 2013-05-23 13:43 UTC (permalink / raw)
  To: Sascha Hauer; +Cc: barebox

Am 23.05.2013 15:35, schrieb Sascha Hauer:
> Hi Oleksij,
>
> On Wed, May 22, 2013 at 09:49:47AM +0200, Oleksij Rempel wrote:
>> Signed-off-by: Oleksij Rempel <linux@rempel-privat.de>
>> Signed-off-by: Antony Pavlov <antonynpavlov@gmail.com>
>> +
>> +/*
>> + * 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 clockCtl1, preDivideSelect, preDivisor, multiplier;
>
> No CamelCase please.

ok. i'll fix it.

>> +static int platform_init(void)
>> +{
>> +	add_generic_device("ar2312_reset", DEVICE_ID_SINGLE, NULL,
>> +			KSEG1ADDR(AR2312_RESETTMR), 0x4,
>> +			IORESOURCE_MEM, NULL);
>> +	watchdog_init();
>> +	flash_init();
>> +	ether_init();
>
> Whether or not the flash/ethernet/serial device is available is board
> specific, not SoC specific, so this should be done in board code. It's
> good to provide helpers to make this simple for the board code though,
> so a good option would be to add a SoC prefix to the functions and call
> it from board code.

Probably it will make sense to have generic type of board. Because this 
will work with most configurations. Since it is WiSoC (Wireless SoC), 
ethernet is on chip too.

> Otherwise I am fine with this patch, but maybe Antony still has some
> comments.


-- 
Regards,
Oleksij

_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [RFC, PATCH v2 2/3] net: add ar231x-eth support
  2013-05-22  7:49 ` [RFC, PATCH v2 2/3] net: add ar231x-eth support Oleksij Rempel
@ 2013-05-24  7:09   ` Sascha Hauer
  2013-05-24  9:14     ` Jean-Christophe PLAGNIOL-VILLARD
  2013-05-25 15:57     ` Oleksij Rempel
  0 siblings, 2 replies; 10+ messages in thread
From: Sascha Hauer @ 2013-05-24  7:09 UTC (permalink / raw)
  To: Oleksij Rempel; +Cc: barebox

On Wed, May 22, 2013 at 09:49:48AM +0200, Oleksij Rempel wrote:
> This driver should work with some Atheros WiSoCs:
> - ar2312, ar2313
> - ar2315, ar2316 ...
> 
> Signed-off-by: Oleksij Rempel <linux@rempel-privat.de>
> ---
>  drivers/net/Kconfig  |   7 +
>  drivers/net/Makefile |   1 +
>  drivers/net/ar231x.c | 429 +++++++++++++++++++++++++++++++++++++++++++++++++++
>  drivers/net/ar231x.h | 219 ++++++++++++++++++++++++++
>  4 files changed, 656 insertions(+)
>  create mode 100644 drivers/net/ar231x.c
>  create mode 100644 drivers/net/ar231x.h
> 
> +
> +	/* FIXME: priv->{t,r}x_ring are virtual addresses,
> +	 * use virt-to-phys convertion */

We use 1:1 mappings, so I think this comment should be removed.

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

What alignment do you need here? This may or may not be safe.

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

This loop looks wrong. You should only receive a single packet for each
call of this function.

> +
> +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->eth_regs = dev_request_mem_region(dev, 0);
> +	/* 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);
> +
> +	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);

Please check the return values of dev_request_mem_region,
mdiobus_register and eth_register. I'm fine with not properly cleaning
up afterwards, but we should be able to notice the user if something
goes wrong here. (Yeah, I know, many network driver don't do so)

Sascha

-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [RFC, PATCH v2 2/3] net: add ar231x-eth support
  2013-05-24  7:09   ` Sascha Hauer
@ 2013-05-24  9:14     ` Jean-Christophe PLAGNIOL-VILLARD
  2013-05-25 15:57     ` Oleksij Rempel
  1 sibling, 0 replies; 10+ messages in thread
From: Jean-Christophe PLAGNIOL-VILLARD @ 2013-05-24  9:14 UTC (permalink / raw)
  To: Sascha Hauer; +Cc: barebox

On 09:09 Fri 24 May     , Sascha Hauer wrote:
> On Wed, May 22, 2013 at 09:49:48AM +0200, Oleksij Rempel wrote:
> > This driver should work with some Atheros WiSoCs:
> > - ar2312, ar2313
> > - ar2315, ar2316 ...
> > 
> > Signed-off-by: Oleksij Rempel <linux@rempel-privat.de>
> > ---
> >  drivers/net/Kconfig  |   7 +
> >  drivers/net/Makefile |   1 +
> >  drivers/net/ar231x.c | 429 +++++++++++++++++++++++++++++++++++++++++++++++++++
> >  drivers/net/ar231x.h | 219 ++++++++++++++++++++++++++
> >  4 files changed, 656 insertions(+)
> >  create mode 100644 drivers/net/ar231x.c
> >  create mode 100644 drivers/net/ar231x.h
> > 
> > +
> > +	/* FIXME: priv->{t,r}x_ring are virtual addresses,
> > +	 * use virt-to-phys convertion */
> 
> We use 1:1 mappings, so I think this comment should be removed.
on mips it's not the case
> 
> > +
> > +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);
> 
> What alignment do you need here? This may or may not be safe.
dma_alloc too

_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [RFC, PATCH v2 2/3] net: add ar231x-eth support
  2013-05-24  7:09   ` Sascha Hauer
  2013-05-24  9:14     ` Jean-Christophe PLAGNIOL-VILLARD
@ 2013-05-25 15:57     ` Oleksij Rempel
  2013-05-28  6:57       ` Sascha Hauer
  1 sibling, 1 reply; 10+ messages in thread
From: Oleksij Rempel @ 2013-05-25 15:57 UTC (permalink / raw)
  To: Sascha Hauer; +Cc: barebox

Am 24.05.2013 09:09, schrieb Sascha Hauer:
> On Wed, May 22, 2013 at 09:49:48AM +0200, Oleksij Rempel wrote:
>> This driver should work with some Atheros WiSoCs:
>> - ar2312, ar2313
>> - ar2315, ar2316 ...
>>
>> Signed-off-by: Oleksij Rempel <linux@rempel-privat.de>
>> ---
>>   drivers/net/Kconfig  |   7 +
>>   drivers/net/Makefile |   1 +
>>   drivers/net/ar231x.c | 429 +++++++++++++++++++++++++++++++++++++++++++++++++++
>>   drivers/net/ar231x.h | 219 ++++++++++++++++++++++++++
>>   4 files changed, 656 insertions(+)
>>   create mode 100644 drivers/net/ar231x.c
>>   create mode 100644 drivers/net/ar231x.h
>>
>> +
>> +	/* FIXME: priv->{t,r}x_ring are virtual addresses,
>> +	 * use virt-to-phys convertion */
>
> We use 1:1 mappings, so I think this comment should be removed.

This part should be fixed after Anthonys "MIPS: add initial cache support"

>> +
>> +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);
>
> What alignment do you need here? This may or may not be safe.

Currently there is no other choice.

>> +
>> +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);
>> +	}
>
> This loop looks wrong. You should only receive a single packet for each
> call of this function.

This loop is needed to filter broadcast packtes. If remove this loop and 
reduce rx buffer, i will get really bad packet losses.

>
>> +
>> +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->eth_regs = dev_request_mem_region(dev, 0);
>> +	/* 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);
>> +
>> +	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);
>
> Please check the return values of dev_request_mem_region,
> mdiobus_register and eth_register. I'm fine with not properly cleaning
> up afterwards, but we should be able to notice the user if something
> goes wrong here. (Yeah, I know, many network driver don't do so)

ok


-- 
Regards,
Oleksij

_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [RFC, PATCH v2 2/3] net: add ar231x-eth support
  2013-05-25 15:57     ` Oleksij Rempel
@ 2013-05-28  6:57       ` Sascha Hauer
  0 siblings, 0 replies; 10+ messages in thread
From: Sascha Hauer @ 2013-05-28  6:57 UTC (permalink / raw)
  To: Oleksij Rempel; +Cc: barebox

On Sat, May 25, 2013 at 05:57:02PM +0200, Oleksij Rempel wrote:
> Am 24.05.2013 09:09, schrieb Sascha Hauer:
> >On Wed, May 22, 2013 at 09:49:48AM +0200, Oleksij Rempel wrote:
> >>This driver should work with some Atheros WiSoCs:
> >>- ar2312, ar2313
> >>- ar2315, ar2316 ...
> >>
> >>Signed-off-by: Oleksij Rempel <linux@rempel-privat.de>
> >>---
> >>  drivers/net/Kconfig  |   7 +
> >>  drivers/net/Makefile |   1 +
> >>  drivers/net/ar231x.c | 429 +++++++++++++++++++++++++++++++++++++++++++++++++++
> >>  drivers/net/ar231x.h | 219 ++++++++++++++++++++++++++
> >>  4 files changed, 656 insertions(+)
> >>  create mode 100644 drivers/net/ar231x.c
> >>  create mode 100644 drivers/net/ar231x.h
> >>
> >>+
> >>+	/* FIXME: priv->{t,r}x_ring are virtual addresses,
> >>+	 * use virt-to-phys convertion */
> >
> >We use 1:1 mappings, so I think this comment should be removed.
> 
> This part should be fixed after Anthonys "MIPS: add initial cache support"
> 
> >>+
> >>+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);
> >
> >What alignment do you need here? This may or may not be safe.
> 
> Currently there is no other choice.
> 
> >>+
> >>+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);
> >>+	}
> >
> >This loop looks wrong. You should only receive a single packet for each
> >call of this function.
> 
> This loop is needed to filter broadcast packtes. If remove this loop
> and reduce rx buffer, i will get really bad packet losses.

What I meant is that you should only pull a single packet out of the
queue each time you enter ar231x_eth_recv. You shouldn't have to reduce
the rx buffer for this.

Anyway, thinking about it it should be fine to call net_receive on all
currently available buffers like you did above. Just keep it like it is
now.

So with the request_mem_region fix this driver should be fine.

Sascha

-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2013-05-28  6:57 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-05-22  7:49 [RFC, PATCH v2 0/3] work on atheros ar2313 Oleksij Rempel
2013-05-22  7:49 ` [RFC, PATCH v2 1/3] MIPS: add Atheros ar531x family support Oleksij Rempel
2013-05-23 13:35   ` Sascha Hauer
2013-05-23 13:43     ` Oleksij Rempel
2013-05-22  7:49 ` [RFC, PATCH v2 2/3] net: add ar231x-eth support Oleksij Rempel
2013-05-24  7:09   ` Sascha Hauer
2013-05-24  9:14     ` Jean-Christophe PLAGNIOL-VILLARD
2013-05-25 15:57     ` Oleksij Rempel
2013-05-28  6:57       ` Sascha Hauer
2013-05-22  7:49 ` [RFC, PATCH v2 3/3] MIPS: ar231x: add netgear-wg102 Oleksij Rempel

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox