summaryrefslogtreecommitdiff
path: root/target/mips
diff options
context:
space:
mode:
authorPhil Sutter <phil@nwl.cc>2014-06-17 03:07:39 +0200
committerWaldemar Brodkorb <wbx@openadk.org>2014-06-18 09:10:35 +0200
commit0d5977574bd73b1312f7c15dce0d027ccbf378ba (patch)
tree4a6aa8db790e8bf5e121302a76e04241ae45d0d4 /target/mips
parentcc0aa555d91ffa1e878e0a85badccdcad6173c7b (diff)
add support for mikrotik rb4xx
Signed-off-by: Phil Sutter <phil@nwl.cc>
Diffstat (limited to 'target/mips')
-rw-r--r--target/mips/kernel/mikrotik-rb4xx53
-rw-r--r--target/mips/mikrotik-rb4xx/patches/3.14.7/0001-mtd-add-rb4xx-nand-driver.patch351
-rw-r--r--target/mips/mikrotik-rb4xx/patches/3.14.7/0002-phy-add-ethtool-ioctl-support-used-by-ag71xx-driver.patch80
-rw-r--r--target/mips/mikrotik-rb4xx/patches/3.14.7/0003-net-add-ag71xx-mac-driver.patch4245
-rw-r--r--target/mips/mikrotik-rb4xx/patches/3.14.7/0004-drivers-link-SPI-drivers-before-MTD-drivers.patch27
-rw-r--r--target/mips/mikrotik-rb4xx/patches/3.14.7/0005-spi-add-various-flags-to-spi_transfer-and-spi_messag.patch34
-rw-r--r--target/mips/mikrotik-rb4xx/patches/3.14.7/0006-spi-add-rb4xx-SPI-driver.patch557
-rw-r--r--target/mips/mikrotik-rb4xx/patches/3.14.7/0007-spi-add-rb4xx-cpld-driver.patch548
-rw-r--r--target/mips/mikrotik-rb4xx/patches/3.14.7/0008-gpio-add-GPIO-latch-driver.patch290
-rw-r--r--target/mips/mikrotik-rb4xx/patches/3.14.7/0009-spi-export-spi_bitbang_bufs-function.patch45
-rw-r--r--target/mips/mikrotik-rb4xx/patches/3.14.7/0010-spi-add-type-field-to-spi_transfer-struct.patch37
-rw-r--r--target/mips/mikrotik-rb4xx/patches/3.14.7/0011-mtd-m25p80-set-SPI-transfer-type.patch29
-rw-r--r--target/mips/mikrotik-rb4xx/patches/3.14.7/0012-mips-ath79-swizzle-PCI-address-for-ar71xx.patch130
-rw-r--r--target/mips/mikrotik-rb4xx/patches/3.14.7/0013-net-add-swconfig-support.patch1859
-rw-r--r--target/mips/mikrotik-rb4xx/patches/3.14.7/0014-phy-add-detach-callback-to-struct-phy_driver.patch46
-rw-r--r--target/mips/mikrotik-rb4xx/patches/3.14.7/0015-phy-add-ar8216-PHY-support.patch3671
-rw-r--r--target/mips/mikrotik-rb4xx/patches/3.14.7/0016-phy-mdio-bitbang-ignore-TA-value.patch44
-rw-r--r--target/mips/mikrotik-rb4xx/patches/3.14.7/0017-MIPS-ath79-fix-maximum-timeout.patch37
-rw-r--r--target/mips/mikrotik-rb4xx/patches/3.14.7/0018-net-allow-PHY-drivers-to-insert-packet-mangle-hooks.patch211
-rw-r--r--target/mips/mikrotik-rb4xx/patches/3.14.7/0019-MIPS-ath79-process-board-cmdline-option.patch26
-rw-r--r--target/mips/mikrotik-rb4xx/patches/3.14.7/0020-spi-ath79-add-fast-flash-read-support.patch202
-rw-r--r--target/mips/mikrotik-rb4xx/patches/3.14.7/0021-phy-add-mdio-boardinfo.patch227
-rw-r--r--target/mips/mikrotik-rb4xx/patches/3.14.7/0022-mips-ath79-add-ath79-ethernet-driver.patch1429
-rw-r--r--target/mips/mikrotik-rb4xx/patches/3.14.7/0023-MIPS-ath79-add-Mikrotik-rb4xx-device-support.patch536
-rw-r--r--target/mips/mikrotik-rb4xx/patches/3.14.7/0024-various-fixups-for-Werror.patch105
-rw-r--r--target/mips/mikrotik-rb4xx/patches/3.14.7/0025-rb4xx_nand-add-partition-for-cfgfs.patch28
-rw-r--r--target/mips/mikrotik-rb4xx/patches/3.14.7/0026-various-fixups-for-ath5k-fixing-system-freezes.patch108
-rw-r--r--target/mips/systems/mikrotik-rb4xx13
28 files changed, 14968 insertions, 0 deletions
diff --git a/target/mips/kernel/mikrotik-rb4xx b/target/mips/kernel/mikrotik-rb4xx
new file mode 100644
index 000000000..ef3e9fdc3
--- /dev/null
+++ b/target/mips/kernel/mikrotik-rb4xx
@@ -0,0 +1,53 @@
+CONFIG_MIPS=y
+CONFIG_ATH79=y
+CONFIG_ATH79_MACH_RB4XX=y
+CONFIG_32BIT=y
+CONFIG_PAGE_SIZE_4KB=y
+CONFIG_HZ=100
+CONFIG_ETHERNET_PACKET_MANGLE=y
+CONFIG_MTD_M25P80=y
+CONFIG_MTD_NAND_ECC=y
+CONFIG_MTD_NAND=y
+CONFIG_MTD_NAND_IDS=y
+CONFIG_MTD_NAND_RB4XX=y
+CONFIG_NET_VENDOR_ATHEROS=y
+CONFIG_AG71XX=y
+CONFIG_AG71XX_AR8216_SUPPORT=y
+CONFIG_PHYLIB=y
+CONFIG_MDIO_BOARDINFO=y
+CONFIG_SWCONFIG=y
+CONFIG_SWCONFIG_LEDS=y
+CONFIG_AR8216_PHY=y
+CONFIG_AR8216_PHY_LEDS=y
+CONFIG_MDIO_BITBANG=y
+CONFIG_MDIO_GPIO=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=1
+CONFIG_SERIAL_8250_RUNTIME_UARTS=1
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
+CONFIG_I2C_GPIO=y
+CONFIG_SPI=y
+CONFIG_SPI_MASTER=y
+CONFIG_SPI_ATH79=y
+CONFIG_SPI_BITBANG=y
+CONFIG_SPI_RB4XX=y
+CONFIG_SPI_RB4XX_CPLD=y
+CONFIG_GPIO_LATCH=y
+CONFIG_GPIO_SYSFS=y
+CONFIG_ATH79_WDT=y
+CONFIG_MMC=y
+CONFIG_MMC_BLOCK=y
+CONFIG_MMC_SPI=y
+CONFIG_LEDS_GPIO=y
+CONFIG_WATCHDOG=y
+CONFIG_ATH79_WDT=y
+CONFIG_USB_SUPPORT=y
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+CONFIG_LEDS_GPIO=y
+CONFIG_GENERIC_PHY=y
diff --git a/target/mips/mikrotik-rb4xx/patches/3.14.7/0001-mtd-add-rb4xx-nand-driver.patch b/target/mips/mikrotik-rb4xx/patches/3.14.7/0001-mtd-add-rb4xx-nand-driver.patch
new file mode 100644
index 000000000..8199de991
--- /dev/null
+++ b/target/mips/mikrotik-rb4xx/patches/3.14.7/0001-mtd-add-rb4xx-nand-driver.patch
@@ -0,0 +1,351 @@
+From 1e692cc0c53202b932eedabd0315107910c5b093 Mon Sep 17 00:00:00 2001
+From: Phil Sutter <phil@nwl.cc>
+Date: Tue, 13 May 2014 00:08:54 +0200
+Subject: [PATCH] mtd: add rb4xx nand driver
+
+---
+ drivers/mtd/nand/Kconfig | 4 +
+ drivers/mtd/nand/Makefile | 1 +
+ drivers/mtd/nand/rb4xx_nand.c | 305 ++++++++++++++++++++++++++++++++++++++++++
+ 3 files changed, 310 insertions(+)
+ create mode 100644 drivers/mtd/nand/rb4xx_nand.c
+
+diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig
+index 90ff447..bb01309 100644
+--- a/drivers/mtd/nand/Kconfig
++++ b/drivers/mtd/nand/Kconfig
+@@ -510,4 +510,8 @@ config MTD_NAND_XWAY
+ Enables support for NAND Flash chips on Lantiq XWAY SoCs. NAND is attached
+ to the External Bus Unit (EBU).
+
++config MTD_NAND_RB4XX
++ tristate "NAND flash driver for RouterBoard 4xx series"
++ depends on MTD_NAND && ATH79_MACH_RB4XX
++
+ endif # MTD_NAND
+diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile
+index 542b568..e2b5e1c 100644
+--- a/drivers/mtd/nand/Makefile
++++ b/drivers/mtd/nand/Makefile
+@@ -31,6 +31,7 @@ obj-$(CONFIG_MTD_NAND_CM_X270) += cmx270_nand.o
+ obj-$(CONFIG_MTD_NAND_PXA3xx) += pxa3xx_nand.o
+ obj-$(CONFIG_MTD_NAND_TMIO) += tmio_nand.o
+ obj-$(CONFIG_MTD_NAND_PLATFORM) += plat_nand.o
++obj-$(CONFIG_MTD_NAND_RB4XX) += rb4xx_nand.o
+ obj-$(CONFIG_MTD_NAND_PASEMI) += pasemi_nand.o
+ obj-$(CONFIG_MTD_NAND_ORION) += orion_nand.o
+ obj-$(CONFIG_MTD_NAND_FSL_ELBC) += fsl_elbc_nand.o
+diff --git a/drivers/mtd/nand/rb4xx_nand.c b/drivers/mtd/nand/rb4xx_nand.c
+new file mode 100644
+index 0000000..5b9841b
+--- /dev/null
++++ b/drivers/mtd/nand/rb4xx_nand.c
+@@ -0,0 +1,305 @@
++/*
++ * NAND flash driver for the MikroTik RouterBoard 4xx series
++ *
++ * Copyright (C) 2008-2011 Gabor Juhos <juhosg@openwrt.org>
++ * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
++ *
++ * This file was based on the driver for Linux 2.6.22 published by
++ * MikroTik for their RouterBoard 4xx series devices.
++ *
++ * 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.
++ */
++
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/mtd/nand.h>
++#include <linux/mtd/mtd.h>
++#include <linux/mtd/partitions.h>
++#include <linux/platform_device.h>
++#include <linux/delay.h>
++#include <linux/io.h>
++#include <linux/gpio.h>
++#include <linux/slab.h>
++
++#include <asm/mach-ath79/ath79.h>
++#include <asm/mach-ath79/rb4xx_cpld.h>
++
++#define DRV_NAME "rb4xx-nand"
++#define DRV_VERSION "0.2.0"
++#define DRV_DESC "NAND flash driver for RouterBoard 4xx series"
++
++#define RB4XX_NAND_GPIO_READY 5
++#define RB4XX_NAND_GPIO_ALE 37
++#define RB4XX_NAND_GPIO_CLE 38
++#define RB4XX_NAND_GPIO_NCE 39
++
++struct rb4xx_nand_info {
++ struct nand_chip chip;
++ struct mtd_info mtd;
++};
++
++/*
++ * We need to use the OLD Yaffs-1 OOB layout, otherwise the RB bootloader
++ * will not be able to find the kernel that we load.
++ */
++static struct nand_ecclayout rb4xx_nand_ecclayout = {
++ .eccbytes = 6,
++ .eccpos = { 8, 9, 10, 13, 14, 15 },
++ .oobavail = 9,
++ .oobfree = { { 0, 4 }, { 6, 2 }, { 11, 2 }, { 4, 1 } }
++};
++
++static struct mtd_partition rb4xx_nand_partitions[] = {
++ {
++ .name = "booter",
++ .offset = 0,
++ .size = (256 * 1024),
++ .mask_flags = MTD_WRITEABLE,
++ },
++ {
++ .name = "kernel",
++ .offset = (256 * 1024),
++ .size = (4 * 1024 * 1024) - (256 * 1024),
++ },
++ {
++ .name = "rootfs",
++ .offset = MTDPART_OFS_NXTBLK,
++ .size = MTDPART_SIZ_FULL,
++ },
++};
++
++static int rb4xx_nand_dev_ready(struct mtd_info *mtd)
++{
++ return gpio_get_value_cansleep(RB4XX_NAND_GPIO_READY);
++}
++
++static void rb4xx_nand_write_cmd(unsigned char cmd)
++{
++ unsigned char data = cmd;
++ int err;
++
++ err = rb4xx_cpld_write(&data, 1);
++ if (err)
++ pr_err("rb4xx_nand: write cmd failed, err=%d\n", err);
++}
++
++static void rb4xx_nand_cmd_ctrl(struct mtd_info *mtd, int cmd,
++ unsigned int ctrl)
++{
++ if (ctrl & NAND_CTRL_CHANGE) {
++ gpio_set_value_cansleep(RB4XX_NAND_GPIO_CLE,
++ (ctrl & NAND_CLE) ? 1 : 0);
++ gpio_set_value_cansleep(RB4XX_NAND_GPIO_ALE,
++ (ctrl & NAND_ALE) ? 1 : 0);
++ gpio_set_value_cansleep(RB4XX_NAND_GPIO_NCE,
++ (ctrl & NAND_NCE) ? 0 : 1);
++ }
++
++ if (cmd != NAND_CMD_NONE)
++ rb4xx_nand_write_cmd(cmd);
++}
++
++static unsigned char rb4xx_nand_read_byte(struct mtd_info *mtd)
++{
++ unsigned char data = 0;
++ int err;
++
++ err = rb4xx_cpld_read(&data, NULL, 1);
++ if (err) {
++ pr_err("rb4xx_nand: read data failed, err=%d\n", err);
++ data = 0xff;
++ }
++
++ return data;
++}
++
++static void rb4xx_nand_write_buf(struct mtd_info *mtd, const unsigned char *buf,
++ int len)
++{
++ int err;
++
++ err = rb4xx_cpld_write(buf, len);
++ if (err)
++ pr_err("rb4xx_nand: write buf failed, err=%d\n", err);
++}
++
++static void rb4xx_nand_read_buf(struct mtd_info *mtd, unsigned char *buf,
++ int len)
++{
++ int err;
++
++ err = rb4xx_cpld_read(buf, NULL, len);
++ if (err)
++ pr_err("rb4xx_nand: read buf failed, err=%d\n", err);
++}
++
++static int rb4xx_nand_probe(struct platform_device *pdev)
++{
++ struct rb4xx_nand_info *info;
++ int ret;
++
++ printk(KERN_INFO DRV_DESC " version " DRV_VERSION "\n");
++
++ ret = gpio_request(RB4XX_NAND_GPIO_READY, "NAND RDY");
++ if (ret) {
++ dev_err(&pdev->dev, "unable to request gpio %d\n",
++ RB4XX_NAND_GPIO_READY);
++ goto err;
++ }
++
++ ret = gpio_direction_input(RB4XX_NAND_GPIO_READY);
++ if (ret) {
++ dev_err(&pdev->dev, "unable to set input mode on gpio %d\n",
++ RB4XX_NAND_GPIO_READY);
++ goto err_free_gpio_ready;
++ }
++
++ ret = gpio_request(RB4XX_NAND_GPIO_ALE, "NAND ALE");
++ if (ret) {
++ dev_err(&pdev->dev, "unable to request gpio %d\n",
++ RB4XX_NAND_GPIO_ALE);
++ goto err_free_gpio_ready;
++ }
++
++ ret = gpio_direction_output(RB4XX_NAND_GPIO_ALE, 0);
++ if (ret) {
++ dev_err(&pdev->dev, "unable to set output mode on gpio %d\n",
++ RB4XX_NAND_GPIO_ALE);
++ goto err_free_gpio_ale;
++ }
++
++ ret = gpio_request(RB4XX_NAND_GPIO_CLE, "NAND CLE");
++ if (ret) {
++ dev_err(&pdev->dev, "unable to request gpio %d\n",
++ RB4XX_NAND_GPIO_CLE);
++ goto err_free_gpio_ale;
++ }
++
++ ret = gpio_direction_output(RB4XX_NAND_GPIO_CLE, 0);
++ if (ret) {
++ dev_err(&pdev->dev, "unable to set output mode on gpio %d\n",
++ RB4XX_NAND_GPIO_CLE);
++ goto err_free_gpio_cle;
++ }
++
++ ret = gpio_request(RB4XX_NAND_GPIO_NCE, "NAND NCE");
++ if (ret) {
++ dev_err(&pdev->dev, "unable to request gpio %d\n",
++ RB4XX_NAND_GPIO_NCE);
++ goto err_free_gpio_cle;
++ }
++
++ ret = gpio_direction_output(RB4XX_NAND_GPIO_NCE, 1);
++ if (ret) {
++ dev_err(&pdev->dev, "unable to set output mode on gpio %d\n",
++ RB4XX_NAND_GPIO_ALE);
++ goto err_free_gpio_nce;
++ }
++
++ info = kzalloc(sizeof(*info), GFP_KERNEL);
++ if (!info) {
++ dev_err(&pdev->dev, "rb4xx-nand: no memory for private data\n");
++ ret = -ENOMEM;
++ goto err_free_gpio_nce;
++ }
++
++ info->chip.priv = &info;
++ info->mtd.priv = &info->chip;
++ info->mtd.owner = THIS_MODULE;
++
++ info->chip.cmd_ctrl = rb4xx_nand_cmd_ctrl;
++ info->chip.dev_ready = rb4xx_nand_dev_ready;
++ info->chip.read_byte = rb4xx_nand_read_byte;
++ info->chip.write_buf = rb4xx_nand_write_buf;
++ info->chip.read_buf = rb4xx_nand_read_buf;
++
++ info->chip.chip_delay = 25;
++ info->chip.ecc.mode = NAND_ECC_SOFT;
++
++ platform_set_drvdata(pdev, info);
++
++ ret = nand_scan_ident(&info->mtd, 1, NULL);
++ if (ret) {
++ ret = -ENXIO;
++ goto err_free_info;
++ }
++
++ if (info->mtd.writesize == 512)
++ info->chip.ecc.layout = &rb4xx_nand_ecclayout;
++
++ ret = nand_scan_tail(&info->mtd);
++ if (ret) {
++ return -ENXIO;
++ goto err_set_drvdata;
++ }
++
++ mtd_device_register(&info->mtd, rb4xx_nand_partitions,
++ ARRAY_SIZE(rb4xx_nand_partitions));
++ if (ret)
++ goto err_release_nand;
++
++ return 0;
++
++err_release_nand:
++ nand_release(&info->mtd);
++err_set_drvdata:
++ platform_set_drvdata(pdev, NULL);
++err_free_info:
++ kfree(info);
++err_free_gpio_nce:
++ gpio_free(RB4XX_NAND_GPIO_NCE);
++err_free_gpio_cle:
++ gpio_free(RB4XX_NAND_GPIO_CLE);
++err_free_gpio_ale:
++ gpio_free(RB4XX_NAND_GPIO_ALE);
++err_free_gpio_ready:
++ gpio_free(RB4XX_NAND_GPIO_READY);
++err:
++ return ret;
++}
++
++static int rb4xx_nand_remove(struct platform_device *pdev)
++{
++ struct rb4xx_nand_info *info = platform_get_drvdata(pdev);
++
++ nand_release(&info->mtd);
++ platform_set_drvdata(pdev, NULL);
++ kfree(info);
++ gpio_free(RB4XX_NAND_GPIO_NCE);
++ gpio_free(RB4XX_NAND_GPIO_CLE);
++ gpio_free(RB4XX_NAND_GPIO_ALE);
++ gpio_free(RB4XX_NAND_GPIO_READY);
++
++ return 0;
++}
++
++static struct platform_driver rb4xx_nand_driver = {
++ .probe = rb4xx_nand_probe,
++ .remove = rb4xx_nand_remove,
++ .driver = {
++ .name = DRV_NAME,
++ .owner = THIS_MODULE,
++ },
++};
++
++static int __init rb4xx_nand_init(void)
++{
++ return platform_driver_register(&rb4xx_nand_driver);
++}
++
++static void __exit rb4xx_nand_exit(void)
++{
++ platform_driver_unregister(&rb4xx_nand_driver);
++}
++
++module_init(rb4xx_nand_init);
++module_exit(rb4xx_nand_exit);
++
++MODULE_DESCRIPTION(DRV_DESC);
++MODULE_VERSION(DRV_VERSION);
++MODULE_AUTHOR("Gabor Juhos <juhosg@openwrt.org>");
++MODULE_AUTHOR("Imre Kaloz <kaloz@openwrt.org>");
++MODULE_LICENSE("GPL v2");
+--
+1.8.5.3
+
diff --git a/target/mips/mikrotik-rb4xx/patches/3.14.7/0002-phy-add-ethtool-ioctl-support-used-by-ag71xx-driver.patch b/target/mips/mikrotik-rb4xx/patches/3.14.7/0002-phy-add-ethtool-ioctl-support-used-by-ag71xx-driver.patch
new file mode 100644
index 000000000..ba7fbfad8
--- /dev/null
+++ b/target/mips/mikrotik-rb4xx/patches/3.14.7/0002-phy-add-ethtool-ioctl-support-used-by-ag71xx-driver.patch
@@ -0,0 +1,80 @@
+From 7b864612a6e3b139a5a607abd0048a19078fe42f Mon Sep 17 00:00:00 2001
+From: Phil Sutter <phil@nwl.cc>
+Date: Wed, 14 May 2014 02:55:06 +0200
+Subject: [PATCH] phy: add ethtool ioctl support, used by ag71xx driver
+
+---
+ drivers/net/phy/phy.c | 44 ++++++++++++++++++++++++++++++++++++++++++++
+ include/linux/phy.h | 1 +
+ 2 files changed, 45 insertions(+)
+
+diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c
+index 76d96b9..9439ef3 100644
+--- a/drivers/net/phy/phy.c
++++ b/drivers/net/phy/phy.c
+@@ -293,6 +293,50 @@ int phy_ethtool_gset(struct phy_device *phydev, struct ethtool_cmd *cmd)
+ }
+ EXPORT_SYMBOL(phy_ethtool_gset);
+
++int phy_ethtool_ioctl(struct phy_device *phydev, void *useraddr)
++{
++ u32 cmd;
++ int tmp;
++ struct ethtool_cmd ecmd = { ETHTOOL_GSET };
++ struct ethtool_value edata = { ETHTOOL_GLINK };
++
++ if (get_user(cmd, (u32 *) useraddr))
++ return -EFAULT;
++
++ switch (cmd) {
++ case ETHTOOL_GSET:
++ phy_ethtool_gset(phydev, &ecmd);
++ if (copy_to_user(useraddr, &ecmd, sizeof(ecmd)))
++ return -EFAULT;
++ return 0;
++
++ case ETHTOOL_SSET:
++ if (copy_from_user(&ecmd, useraddr, sizeof(ecmd)))
++ return -EFAULT;
++ return phy_ethtool_sset(phydev, &ecmd);
++
++ case ETHTOOL_NWAY_RST:
++ /* if autoneg is off, it's an error */
++ tmp = phy_read(phydev, MII_BMCR);
++ if (tmp & BMCR_ANENABLE) {
++ tmp |= (BMCR_ANRESTART);
++ phy_write(phydev, MII_BMCR, tmp);
++ return 0;
++ }
++ return -EINVAL;
++
++ case ETHTOOL_GLINK:
++ edata.data = (phy_read(phydev,
++ MII_BMSR) & BMSR_LSTATUS) ? 1 : 0;
++ if (copy_to_user(useraddr, &edata, sizeof(edata)))
++ return -EFAULT;
++ return 0;
++ }
++
++ return -EOPNOTSUPP;
++}
++EXPORT_SYMBOL(phy_ethtool_ioctl);
++
+ /**
+ * phy_mii_ioctl - generic PHY MII ioctl interface
+ * @phydev: the phy_device struct
+diff --git a/include/linux/phy.h b/include/linux/phy.h
+index 565188c..9ab0d79 100644
+--- a/include/linux/phy.h
++++ b/include/linux/phy.h
+@@ -628,6 +628,7 @@ void phy_stop_machine(struct phy_device *phydev);
+ int phy_ethtool_sset(struct phy_device *phydev, struct ethtool_cmd *cmd);
+ int phy_ethtool_gset(struct phy_device *phydev, struct ethtool_cmd *cmd);
+ int phy_mii_ioctl(struct phy_device *phydev, struct ifreq *ifr, int cmd);
++int phy_ethtool_ioctl(struct phy_device *phydev, void *useraddr);
+ int phy_start_interrupts(struct phy_device *phydev);
+ void phy_print_status(struct phy_device *phydev);
+ void phy_device_free(struct phy_device *phydev);
+--
+1.8.5.3
+
diff --git a/target/mips/mikrotik-rb4xx/patches/3.14.7/0003-net-add-ag71xx-mac-driver.patch b/target/mips/mikrotik-rb4xx/patches/3.14.7/0003-net-add-ag71xx-mac-driver.patch
new file mode 100644
index 000000000..1915c184c
--- /dev/null
+++ b/target/mips/mikrotik-rb4xx/patches/3.14.7/0003-net-add-ag71xx-mac-driver.patch
@@ -0,0 +1,4245 @@
+From c5eb03f91f9185f4813431692f36db3862716a35 Mon Sep 17 00:00:00 2001
+From: Phil Sutter <phil@nwl.cc>
+Date: Tue, 13 May 2014 00:12:37 +0200
+Subject: [PATCH] net: add ag71xx mac driver
+
+---
+ arch/mips/include/asm/mach-ath79/ag71xx_platform.h | 65 +
+ drivers/net/ethernet/atheros/Kconfig | 2 +
+ drivers/net/ethernet/atheros/Makefile | 1 +
+ drivers/net/ethernet/atheros/ag71xx/Kconfig | 33 +
+ drivers/net/ethernet/atheros/ag71xx/Makefile | 15 +
+ drivers/net/ethernet/atheros/ag71xx/ag71xx.h | 476 +++++++
+ .../net/ethernet/atheros/ag71xx/ag71xx_ar7240.c | 1202 ++++++++++++++++++
+ .../net/ethernet/atheros/ag71xx/ag71xx_ar8216.c | 44 +
+ .../net/ethernet/atheros/ag71xx/ag71xx_debugfs.c | 284 +++++
+ .../net/ethernet/atheros/ag71xx/ag71xx_ethtool.c | 124 ++
+ drivers/net/ethernet/atheros/ag71xx/ag71xx_main.c | 1325 ++++++++++++++++++++
+ drivers/net/ethernet/atheros/ag71xx/ag71xx_mdio.c | 318 +++++
+ drivers/net/ethernet/atheros/ag71xx/ag71xx_phy.c | 235 ++++
+ 13 files changed, 4124 insertions(+)
+ create mode 100644 arch/mips/include/asm/mach-ath79/ag71xx_platform.h
+ create mode 100644 drivers/net/ethernet/atheros/ag71xx/Kconfig
+ create mode 100644 drivers/net/ethernet/atheros/ag71xx/Makefile
+ create mode 100644 drivers/net/ethernet/atheros/ag71xx/ag71xx.h
+ create mode 100644 drivers/net/ethernet/atheros/ag71xx/ag71xx_ar7240.c
+ create mode 100644 drivers/net/ethernet/atheros/ag71xx/ag71xx_ar8216.c
+ create mode 100644 drivers/net/ethernet/atheros/ag71xx/ag71xx_debugfs.c
+ create mode 100644 drivers/net/ethernet/atheros/ag71xx/ag71xx_ethtool.c
+ create mode 100644 drivers/net/ethernet/atheros/ag71xx/ag71xx_main.c
+ create mode 100644 drivers/net/ethernet/atheros/ag71xx/ag71xx_mdio.c
+ create mode 100644 drivers/net/ethernet/atheros/ag71xx/ag71xx_phy.c
+
+diff --git a/arch/mips/include/asm/mach-ath79/ag71xx_platform.h b/arch/mips/include/asm/mach-ath79/ag71xx_platform.h
+new file mode 100644
+index 0000000..d46dc4e
+--- /dev/null
++++ b/arch/mips/include/asm/mach-ath79/ag71xx_platform.h
+@@ -0,0 +1,65 @@
++/*
++ * Atheros AR71xx SoC specific platform data definitions
++ *
++ * Copyright (C) 2008-2012 Gabor Juhos <juhosg@openwrt.org>
++ * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
++ *
++ * 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.
++ */
++
++#ifndef __ASM_MACH_ATH79_PLATFORM_H
++#define __ASM_MACH_ATH79_PLATFORM_H
++
++#include <linux/if_ether.h>
++#include <linux/skbuff.h>
++#include <linux/phy.h>
++#include <linux/spi/spi.h>
++
++struct ag71xx_switch_platform_data {
++ u8 phy4_mii_en:1;
++ u8 phy_poll_mask;
++};
++
++struct ag71xx_platform_data {
++ phy_interface_t phy_if_mode;
++ u32 phy_mask;
++ int speed;
++ int duplex;
++ u32 reset_bit;
++ u8 mac_addr[ETH_ALEN];
++ struct device *mii_bus_dev;
++
++ u8 has_gbit:1;
++ u8 is_ar91xx:1;
++ u8 is_ar7240:1;
++ u8 is_ar724x:1;
++ u8 has_ar8216:1;
++
++ struct ag71xx_switch_platform_data *switch_data;
++
++ void (*ddr_flush)(void);
++ void (*set_speed)(int speed);
++
++ u32 fifo_cfg1;
++ u32 fifo_cfg2;
++ u32 fifo_cfg3;
++
++ unsigned int max_frame_len;
++ unsigned int desc_pktlen_mask;
++};
++
++struct ag71xx_mdio_platform_data {
++ u32 phy_mask;
++ u8 builtin_switch:1;
++ u8 is_ar7240:1;
++ u8 is_ar9330:1;
++ u8 is_ar934x:1;
++ unsigned long mdio_clock;
++ unsigned long ref_clock;
++
++ void (*reset)(struct mii_bus *bus);
++};
++
++#endif /* __ASM_MACH_ATH79_PLATFORM_H */
+diff --git a/drivers/net/ethernet/atheros/Kconfig b/drivers/net/ethernet/atheros/Kconfig
+index 58ad37c..1fae572 100644
+--- a/drivers/net/ethernet/atheros/Kconfig
++++ b/drivers/net/ethernet/atheros/Kconfig
+@@ -80,4 +80,6 @@ config ALX
+ To compile this driver as a module, choose M here. The module
+ will be called alx.
+
++source drivers/net/ethernet/atheros/ag71xx/Kconfig
++
+ endif # NET_VENDOR_ATHEROS
+diff --git a/drivers/net/ethernet/atheros/Makefile b/drivers/net/ethernet/atheros/Makefile
+index 5cf1c65..d1c5a49 100644
+--- a/drivers/net/ethernet/atheros/Makefile
++++ b/drivers/net/ethernet/atheros/Makefile
+@@ -2,6 +2,7 @@
+ # Makefile for the Atheros network device drivers.
+ #
+
++obj-$(CONFIG_AG71XX) += ag71xx/
+ obj-$(CONFIG_ATL1) += atlx/
+ obj-$(CONFIG_ATL2) += atlx/
+ obj-$(CONFIG_ATL1E) += atl1e/
+diff --git a/drivers/net/ethernet/atheros/ag71xx/Kconfig b/drivers/net/ethernet/atheros/ag71xx/Kconfig
+new file mode 100644
+index 0000000..42d544f
+--- /dev/null
++++ b/drivers/net/ethernet/atheros/ag71xx/Kconfig
+@@ -0,0 +1,33 @@
++config AG71XX
++ tristate "Atheros AR7XXX/AR9XXX built-in ethernet mac support"
++ depends on ATH79
++ select PHYLIB
++ help
++ If you wish to compile a kernel for AR7XXX/91XXX and enable
++ ethernet support, then you should always answer Y to this.
++
++if AG71XX
++
++config AG71XX_DEBUG
++ bool "Atheros AR71xx built-in ethernet driver debugging"
++ default n
++ help
++ Atheros AR71xx built-in ethernet driver debugging messages.
++
++config AG71XX_DEBUG_FS
++ bool "Atheros AR71xx built-in ethernet driver debugfs support"
++ depends on DEBUG_FS
++ default n
++ help
++ Say Y, if you need access to various statistics provided by
++ the ag71xx driver.
++
++config AG71XX_AR8216_SUPPORT
++ bool "special support for the Atheros AR8216 switch"
++ default n
++ default y if ATH79_MACH_WNR2000 || ATH79_MACH_MZK_W04NU
++ help
++ Say 'y' here if you want to enable special support for the
++ Atheros AR8216 switch found on some boards.
++
++endif
+diff --git a/drivers/net/ethernet/atheros/ag71xx/Makefile b/drivers/net/ethernet/atheros/ag71xx/Makefile
+new file mode 100644
+index 0000000..b3ec408
+--- /dev/null
++++ b/drivers/net/ethernet/atheros/ag71xx/Makefile
+@@ -0,0 +1,15 @@
++#
++# Makefile for the Atheros AR71xx built-in ethernet macs
++#
++
++ag71xx-y += ag71xx_main.o
++ag71xx-y += ag71xx_ethtool.o
++ag71xx-y += ag71xx_phy.o
++ag71xx-y += ag71xx_mdio.o
++ag71xx-y += ag71xx_ar7240.o
++
++ag71xx-$(CONFIG_AG71XX_DEBUG_FS) += ag71xx_debugfs.o
++ag71xx-$(CONFIG_AG71XX_AR8216_SUPPORT) += ag71xx_ar8216.o
++
++obj-$(CONFIG_AG71XX) += ag71xx.o
++
+diff --git a/drivers/net/ethernet/atheros/ag71xx/ag71xx.h b/drivers/net/ethernet/atheros/ag71xx/ag71xx.h
+new file mode 100644
+index 0000000..f6d85b9
+--- /dev/null
++++ b/drivers/net/ethernet/atheros/ag71xx/ag71xx.h
+@@ -0,0 +1,476 @@
++/*
++ * Atheros AR71xx built-in ethernet mac driver
++ *
++ * Copyright (C) 2008-2010 Gabor Juhos <juhosg@openwrt.org>
++ * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
++ *
++ * Based on Atheros' AG7100 driver
++ *
++ * 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.
++ */
++
++#ifndef __AG71XX_H
++#define __AG71XX_H
++
++#include <linux/kernel.h>
++#include <linux/version.h>
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/types.h>
++#include <linux/random.h>
++#include <linux/spinlock.h>
++#include <linux/interrupt.h>
++#include <linux/platform_device.h>
++#include <linux/ethtool.h>
++#include <linux/etherdevice.h>
++#include <linux/if_vlan.h>
++#include <linux/phy.h>
++#include <linux/skbuff.h>
++#include <linux/dma-mapping.h>
++#include <linux/workqueue.h>
++
++#include <linux/bitops.h>
++
++#include <asm/mach-ath79/ar71xx_regs.h>
++#include <asm/mach-ath79/ath79.h>
++#include <asm/mach-ath79/ag71xx_platform.h>
++
++#define AG71XX_DRV_NAME "ag71xx"
++#define AG71XX_DRV_VERSION "0.5.35"
++
++#define AG71XX_NAPI_WEIGHT 64
++#define AG71XX_OOM_REFILL (1 + HZ/10)
++
++#define AG71XX_INT_ERR (AG71XX_INT_RX_BE | AG71XX_INT_TX_BE)
++#define AG71XX_INT_TX (AG71XX_INT_TX_PS)
++#define AG71XX_INT_RX (AG71XX_INT_RX_PR | AG71XX_INT_RX_OF)
++
++#define AG71XX_INT_POLL (AG71XX_INT_RX | AG71XX_INT_TX)
++#define AG71XX_INT_INIT (AG71XX_INT_ERR | AG71XX_INT_POLL)
++
++#define AG71XX_TX_MTU_LEN 1540
++
++#define AG71XX_TX_RING_SIZE_DEFAULT 32
++#define AG71XX_RX_RING_SIZE_DEFAULT 128
++
++#define AG71XX_TX_RING_SIZE_MAX 32
++#define AG71XX_RX_RING_SIZE_MAX 128
++
++#ifdef CONFIG_AG71XX_DEBUG
++#define DBG(fmt, args...) pr_debug(fmt, ## args)
++#else
++#define DBG(fmt, args...) do {} while (0)
++#endif
++
++#define ag71xx_assert(_cond) \
++do { \
++ if (_cond) \
++ break; \
++ printk("%s,%d: assertion failed\n", __FILE__, __LINE__); \
++ BUG(); \
++} while (0)
++
++struct ag71xx_desc {
++ u32 data;
++ u32 ctrl;
++#define DESC_EMPTY BIT(31)
++#define DESC_MORE BIT(24)
++#define DESC_PKTLEN_M 0xfff
++ u32 next;
++ u32 pad;
++} __attribute__((aligned(4)));
++
++struct ag71xx_buf {
++ union {
++ struct sk_buff *skb;
++ void *rx_buf;
++ };
++ struct ag71xx_desc *desc;
++ union {
++ dma_addr_t dma_addr;
++ unsigned long timestamp;
++ };
++ unsigned int len;
++};
++
++struct ag71xx_ring {
++ struct ag71xx_buf *buf;
++ u8 *descs_cpu;
++ dma_addr_t descs_dma;
++ unsigned int desc_size;
++ unsigned int curr;
++ unsigned int dirty;
++ unsigned int size;
++};
++
++struct ag71xx_mdio {
++ struct mii_bus *mii_bus;
++ int mii_irq[PHY_MAX_ADDR];
++ void __iomem *mdio_base;
++ struct ag71xx_mdio_platform_data *pdata;
++};
++
++struct ag71xx_int_stats {
++ unsigned long rx_pr;
++ unsigned long rx_be;
++ unsigned long rx_of;
++ unsigned long tx_ps;
++ unsigned long tx_be;
++ unsigned long tx_ur;
++ unsigned long total;
++};
++
++struct ag71xx_napi_stats {
++ unsigned long napi_calls;
++ unsigned long rx_count;
++ unsigned long rx_packets;
++ unsigned long rx_packets_max;
++ unsigned long tx_count;
++ unsigned long tx_packets;
++ unsigned long tx_packets_max;
++
++ unsigned long rx[AG71XX_NAPI_WEIGHT + 1];
++ unsigned long tx[AG71XX_NAPI_WEIGHT + 1];
++};
++
++struct ag71xx_debug {
++ struct dentry *debugfs_dir;
++
++ struct ag71xx_int_stats int_stats;
++ struct ag71xx_napi_stats napi_stats;
++};
++
++struct ag71xx {
++ void __iomem *mac_base;
++
++ spinlock_t lock;
++ struct platform_device *pdev;
++ struct net_device *dev;
++ struct napi_struct napi;
++ u32 msg_enable;
++
++ struct ag71xx_desc *stop_desc;