diff options
| -rw-r--r-- | target/linux/ar71xx/config-2.6.28 | 1 | ||||
| -rw-r--r-- | target/linux/ar71xx/config-2.6.30 | 1 | ||||
| -rw-r--r-- | target/linux/ar71xx/config-2.6.31 | 1 | ||||
| -rw-r--r-- | target/linux/ar71xx/config-2.6.32 | 1 | ||||
| -rw-r--r-- | target/linux/ar71xx/files/drivers/net/phy/rtl8366_smi.c | 661 | ||||
| -rw-r--r-- | target/linux/ar71xx/files/include/linux/rtl8366_smi.h | 19 | ||||
| -rw-r--r-- | target/linux/ar71xx/patches-2.6.28/204-rtl8366-smi-driver.patch | 21 | ||||
| -rw-r--r-- | target/linux/ar71xx/patches-2.6.30/204-rtl8366-smi-driver.patch | 21 | ||||
| -rw-r--r-- | target/linux/ar71xx/patches-2.6.31/204-rtl8366-smi-driver.patch | 21 | ||||
| -rw-r--r-- | target/linux/ar71xx/patches-2.6.32/204-rtl8366-smi-driver.patch | 21 | 
10 files changed, 768 insertions, 0 deletions
diff --git a/target/linux/ar71xx/config-2.6.28 b/target/linux/ar71xx/config-2.6.28 index b15525915..83587906e 100644 --- a/target/linux/ar71xx/config-2.6.28 +++ b/target/linux/ar71xx/config-2.6.28 @@ -162,6 +162,7 @@ CONFIG_PHYLIB=y  # CONFIG_PROBE_INITRD_HEADER is not set  # CONFIG_R6040 is not set  CONFIG_RTL8306_PHY=y +CONFIG_RTL8366_SMI=y  CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y  # CONFIG_SCSI_DMA is not set  # CONFIG_SERIAL_8250_EXTENDED is not set diff --git a/target/linux/ar71xx/config-2.6.30 b/target/linux/ar71xx/config-2.6.30 index 0db13af3c..3cedfdc46 100644 --- a/target/linux/ar71xx/config-2.6.30 +++ b/target/linux/ar71xx/config-2.6.30 @@ -166,6 +166,7 @@ CONFIG_PHYLIB=y  # CONFIG_PNX8550_STB810 is not set  # CONFIG_PROBE_INITRD_HEADER is not set  CONFIG_RTL8306_PHY=y +CONFIG_RTL8366_SMI=y  CONFIG_SCHED_OMIT_FRAME_POINTER=y  # CONFIG_SCSI_DMA is not set  # CONFIG_SERIAL_8250_EXTENDED is not set diff --git a/target/linux/ar71xx/config-2.6.31 b/target/linux/ar71xx/config-2.6.31 index 2e4a56be4..0615a50f4 100644 --- a/target/linux/ar71xx/config-2.6.31 +++ b/target/linux/ar71xx/config-2.6.31 @@ -169,6 +169,7 @@ CONFIG_PHYLIB=y  # CONFIG_PNX8550_STB810 is not set  # CONFIG_PROBE_INITRD_HEADER is not set  CONFIG_RTL8306_PHY=y +CONFIG_RTL8366_SMI=y  CONFIG_SCHED_OMIT_FRAME_POINTER=y  # CONFIG_SCSI_DMA is not set  # CONFIG_SERIAL_8250_EXTENDED is not set diff --git a/target/linux/ar71xx/config-2.6.32 b/target/linux/ar71xx/config-2.6.32 index dcca7d22b..f1a69bc0b 100644 --- a/target/linux/ar71xx/config-2.6.32 +++ b/target/linux/ar71xx/config-2.6.32 @@ -173,6 +173,7 @@ CONFIG_PHYLIB=y  # CONFIG_PNX8550_STB810 is not set  # CONFIG_PROBE_INITRD_HEADER is not set  CONFIG_RTL8306_PHY=y +CONFIG_RTL8366_SMI=y  CONFIG_SCHED_OMIT_FRAME_POINTER=y  # CONFIG_SCSI_DMA is not set  # CONFIG_SERIAL_8250_EXTENDED is not set diff --git a/target/linux/ar71xx/files/drivers/net/phy/rtl8366_smi.c b/target/linux/ar71xx/files/drivers/net/phy/rtl8366_smi.c new file mode 100644 index 000000000..e43f8a2d0 --- /dev/null +++ b/target/linux/ar71xx/files/drivers/net/phy/rtl8366_smi.c @@ -0,0 +1,661 @@ +/* + * Platform driver for the Realtek RTL8366 ethernet switch + * + * Copyright (C) 2009 Gabor Juhos <juhosg@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. + */ + +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/init.h> +#include <linux/platform_device.h> +#include <linux/delay.h> +#include <linux/gpio.h> +#include <linux/spinlock.h> +#include <linux/skbuff.h> +#include <linux/phy.h> +#include <linux/rtl8366_smi.h> + +//#define DEBUG	1 + +#define RTL8366_SMI_DRIVER_NAME	"rtl8366-smi" +#define RTL8366_SMI_DRIVER_DESC	"Realtek RTL8366 switch driver" +#define RTL8366_SMI_DRIVER_VER	"0.1.0" + +#define RTL8366S_PHY_NO_MAX		4 +#define RTL8366S_PHY_PAGE_MAX		7 +#define RTL8366S_PHY_ADDR_MAX		31 + +#define RTL8366S_CHIP_VERSION_CTRL_REG	0x0104 +#define RTL8366S_CHIP_VERSION_MASK	0xf +#define RTL8366S_CHIP_ID_REG		0x0105 +#define RTL8366S_CHIP_ID_8366		0x8366 + +/* PHY registers control */ +#define RTL8366S_PHY_ACCESS_CTRL_REG	0x8028 +#define RTL8366S_PHY_ACCESS_DATA_REG	0x8029 + +#define RTL8366S_PHY_CTRL_READ		1 +#define RTL8366S_PHY_CTRL_WRITE		0 + +#define RTL8366S_PHY_REG_MASK		0x1f +#define RTL8366S_PHY_PAGE_OFFSET	5 +#define RTL8366S_PHY_PAGE_MASK		(0x7 << 5) +#define RTL8366S_PHY_NO_OFFSET		9 +#define RTL8366S_PHY_NO_MASK		(0x1f << 9) + +#define RTL8366_SMI_ACK_RETRY_COUNT	5 +#define RTL8366_SMI_CLK_DELAY		10 /* nsec */ + +struct rtl8366_smi { +	struct platform_device			*pdev; +	struct rtl8366_smi_platform_data	*pdata; +	spinlock_t				lock; +	struct mii_bus				*mii_bus; +	int					mii_irq[PHY_MAX_ADDR]; +}; + +static inline void rtl8366_smi_clk_delay(struct rtl8366_smi *smi) +{ +	ndelay(RTL8366_SMI_CLK_DELAY); +} + +static void rtl8366_smi_start(struct rtl8366_smi *smi) +{ +	unsigned int sda = smi->pdata->gpio_sda; +	unsigned int sck = smi->pdata->gpio_sck; + +	/* +	 * Set GPIO pins to output mode, with initial state: +	 * SCK = 0, SDA = 1 +	 */ +	gpio_direction_output(sck, 0); +	gpio_direction_output(sda, 1); +	rtl8366_smi_clk_delay(smi); + +	/* CLK 1: 0 -> 1, 1 -> 0 */ +	gpio_set_value(sck, 1); +	rtl8366_smi_clk_delay(smi); +	gpio_set_value(sck, 0); +	rtl8366_smi_clk_delay(smi); + +	/* CLK 2: */ +	gpio_set_value(sck, 1); +	rtl8366_smi_clk_delay(smi); +	gpio_set_value(sda, 0); +	rtl8366_smi_clk_delay(smi); +	gpio_set_value(sck, 0); +	rtl8366_smi_clk_delay(smi); +	gpio_set_value(sda, 1); +} + +static void rtl8366_smi_stop(struct rtl8366_smi *smi) +{ +	unsigned int sda = smi->pdata->gpio_sda; +	unsigned int sck = smi->pdata->gpio_sck; + +	rtl8366_smi_clk_delay(smi); +	gpio_set_value(sda, 0); +	gpio_set_value(sck, 1); +	rtl8366_smi_clk_delay(smi); +	gpio_set_value(sda, 1); +	rtl8366_smi_clk_delay(smi); +	gpio_set_value(sck, 1); +	rtl8366_smi_clk_delay(smi); +	gpio_set_value(sck, 0); +	rtl8366_smi_clk_delay(smi); +	gpio_set_value(sck, 1); + +	/* add a click */ +	rtl8366_smi_clk_delay(smi); +	gpio_set_value(sck, 0); +	rtl8366_smi_clk_delay(smi); +	gpio_set_value(sck, 1); + +	/* set GPIO pins to input mode */ +	gpio_direction_input(sda); +	gpio_direction_input(sck); +} + +static void rtl8366_smi_write_bits(struct rtl8366_smi *smi, u32 data, u32 len) +{ +	unsigned int sda = smi->pdata->gpio_sda; +	unsigned int sck = smi->pdata->gpio_sck; + +	for (; len > 0; len--) { +		rtl8366_smi_clk_delay(smi); + +		/* prepare data */ +		if ( data & ( 1 << (len - 1)) ) +			gpio_set_value(sda, 1); +		else +			gpio_set_value(sda, 0); +		rtl8366_smi_clk_delay(smi); + +		/* clocking */ +		gpio_set_value(sck, 1); +		rtl8366_smi_clk_delay(smi); +		gpio_set_value(sck, 0); +	} +} + +static void rtl8366_smi_read_bits(struct rtl8366_smi *smi, u32 len, u32 *data) +{ +	unsigned int sda = smi->pdata->gpio_sda; +	unsigned int sck = smi->pdata->gpio_sck; + +	gpio_direction_input(sda); + +	for (*data = 0; len > 0; len--) { +		u32 u; + +		rtl8366_smi_clk_delay(smi); + +		/* clocking */ +		gpio_set_value(sck, 1); +		rtl8366_smi_clk_delay(smi); +		u = gpio_get_value(sda); +		gpio_set_value(sck, 0); + +		*data |= (u << (len - 1)); +	} + +	gpio_direction_output(sda, 0); +} + +static int rtl8366_smi_wait_for_ack(struct rtl8366_smi *smi) +{ +	int retry_cnt; + +	retry_cnt = 0; +	do { +		u32 ack; + +		rtl8366_smi_read_bits(smi, 1, &ack); +		if (ack == 0) +			break; + +		if (++retry_cnt > RTL8366_SMI_ACK_RETRY_COUNT) +			return -EIO; +	} while (1); + +	return 0; +} + +static int rtl8366_smi_write_byte(struct rtl8366_smi *smi, u8 data) +{ +	rtl8366_smi_write_bits(smi, data, 8); +	return rtl8366_smi_wait_for_ack(smi); +} + +static int rtl8366_smi_read_byte0(struct rtl8366_smi *smi, u8 *data) +{ +	u32 t; + +	/* read data */ +	rtl8366_smi_read_bits(smi, 8, &t); +	*data = (t & 0xff); + +	/* send an ACK */ +	rtl8366_smi_write_bits(smi, 0x00, 1); + +	return 0; +} + +static int rtl8366_smi_read_byte1(struct rtl8366_smi *smi, u8 *data) +{ +	u32 t; + +	/* read data */ +	rtl8366_smi_read_bits(smi, 8, &t); +	*data = (t & 0xff); + +	/* send an ACK */ +	rtl8366_smi_write_bits(smi, 0x01, 1); + +	return 0; +} + +static int rtl8366_smi_read_reg(struct rtl8366_smi *smi, u32 addr, u32 *data) +{ +	unsigned long flags; +	u8 lo = 0; +	u8 hi = 0; +	int ret; + +	spin_lock_irqsave(&smi->lock, flags); + +	rtl8366_smi_start(smi); + +	/* send READ command */ +	ret = rtl8366_smi_write_byte(smi, 0x0a << 4 | 0x04 << 1 | 0x01); +	if (ret) +		goto out; + +	/* set ADDR[7:0] */ +	ret = rtl8366_smi_write_byte(smi, addr & 0xff); +	if (ret) +		goto out; + +	/* set ADDR[15:8] */ +	ret = rtl8366_smi_write_byte(smi, addr >> 8); +	if (ret) +		goto out; + +	/* read DATA[7:0] */ +	rtl8366_smi_read_byte0(smi, &lo); +	/* read DATA[15:8] */ +	rtl8366_smi_read_byte1(smi, &hi); + +	*data = ((u32) lo) | (((u32) hi) << 8); + +	ret = 0; + + out: +	rtl8366_smi_stop(smi); +	spin_unlock_irqrestore(&smi->lock, flags); + +	return ret; +} + +static int rtl8366_smi_write_reg(struct rtl8366_smi *smi, u32 addr, u32 data) +{ +	unsigned long flags; +	int ret; + +	spin_lock_irqsave(&smi->lock, flags); + +	rtl8366_smi_start(smi); + +	/* send WRITE command */ +	ret = rtl8366_smi_write_byte(smi, 0x0a << 4 | 0x04 << 1 | 0x00); +	if (ret) +		goto out; + +	/* set ADDR[7:0] */ +	ret = rtl8366_smi_write_byte(smi, addr & 0xff); +	if (ret) +		goto out; + +	/* set ADDR[15:8] */ +	ret = rtl8366_smi_write_byte(smi, addr >> 8); +	if (ret) +		goto out; + +	/* write DATA[7:0] */ +	ret = rtl8366_smi_write_byte(smi, data & 0xff); +	if (ret) +		goto out; + +	/* write DATA[15:8] */ +	ret = rtl8366_smi_write_byte(smi, data >> 8); +	if (ret) +		goto out; + +	ret = 0; + + out: +	rtl8366_smi_stop(smi); +	spin_unlock_irqrestore(&smi->lock, flags); + +	return ret; +} + +static int rtl8366_smi_read_phy_reg(struct rtl8366_smi *smi, +				    u32 phy_no, u32 page, u32 addr, u32 *data) +{ +	u32 reg; +	int ret; + +	if (phy_no > RTL8366S_PHY_NO_MAX) +		return -EINVAL; + +	if (page > RTL8366S_PHY_PAGE_MAX) +		return -EINVAL; + +	if (addr > RTL8366S_PHY_ADDR_MAX) +		return -EINVAL; + +	ret = rtl8366_smi_write_reg(smi, RTL8366S_PHY_ACCESS_CTRL_REG, +				    RTL8366S_PHY_CTRL_READ); +	if (ret) +		return ret; + +	reg = 0x8000 | (1 << (phy_no + RTL8366S_PHY_NO_OFFSET)) | +	      ((page << RTL8366S_PHY_PAGE_OFFSET) & RTL8366S_PHY_PAGE_MASK) | +	      (addr & RTL8366S_PHY_REG_MASK); + +	ret = rtl8366_smi_write_reg(smi, reg, 0); +	if (ret) +		return ret; + +	ret = rtl8366_smi_read_reg(smi, RTL8366S_PHY_ACCESS_DATA_REG, data); +	if (ret) +		return ret; + +	return 0; +} + +static int rtl8366_smi_write_phy_reg(struct rtl8366_smi *smi, +				     u32 phy_no, u32 page, u32 addr, u32 data) +{ +	u32 reg; +	int ret; + +	if (phy_no > RTL8366S_PHY_NO_MAX) +		return -EINVAL; + +	if (page > RTL8366S_PHY_PAGE_MAX) +		return -EINVAL; + +	if (addr > RTL8366S_PHY_ADDR_MAX) +		return -EINVAL; + +	ret = rtl8366_smi_write_reg(smi, RTL8366S_PHY_ACCESS_CTRL_REG, +				    RTL8366S_PHY_CTRL_WRITE); +	if (ret) +		return ret; + +	reg = 0x8000 | (1 << (phy_no + RTL8366S_PHY_NO_OFFSET)) | +	      ((page << RTL8366S_PHY_PAGE_OFFSET) & RTL8366S_PHY_PAGE_MASK) | +	      (addr & RTL8366S_PHY_REG_MASK); + +	ret = rtl8366_smi_write_reg(smi, reg, data); +	if (ret) +		return ret; + +	return 0; +} + +#ifdef DEBUG +static void rtl8366_smi_dump_regs(struct rtl8366_smi *smi) +{ +	u32 t; +	int err; +	int i; + +	for (i = 0; i < 0x200; i++) { +		err = rtl8366_smi_read_reg(smi, i, &t); +		if (err) { +			dev_err(&smi->pdev->dev, +				"unable to read register %04x\n", i); +			return; +		} +		dev_info(&smi->pdev->dev, "reg %04x: %04x\n", i, t); +	} + +	for (i = 0; i <= RTL8366S_PHY_NO_MAX; i++) { +		int j; + +		for (j = 0; j <= RTL8366S_PHY_ADDR_MAX; j++) { +			err = rtl8366_smi_read_phy_reg(smi, i, 0, j, &t); +			if (err) { +				dev_err(&smi->pdev->dev, +					"unable to read PHY%u:%02x register\n", +					i, j); +				return; +			} +			dev_info(&smi->pdev->dev, +				 "PHY%u:%02x: %04x\n", i, j, t); +		} +	} +} +#else +static inline void rtl8366_smi_dump_regs(struct rtl8366_smi *smi) {} +#endif + +static int rtl8366_smi_mii_read(struct mii_bus *bus, int addr, int reg) +{ +	struct rtl8366_smi *smi = bus->priv; +	u32 val = 0; +	int err; + +	err = rtl8366_smi_read_phy_reg(smi, addr, 0, reg, &val); +	if (err) +		return 0xffff; + +	return val; +} + +static int rtl8366_smi_mii_write(struct mii_bus *bus, int addr, int reg, +				     u16 val) +{ +	struct rtl8366_smi *smi = bus->priv; +	u32 t; +	int err; + +	err = rtl8366_smi_write_phy_reg(smi, addr, 0, reg, val); +	/* flush write */ +	(void) rtl8366_smi_read_phy_reg(smi, addr, 0, reg, &t); + +	return err; +} + +static int rtl8366_smi_mii_init(struct rtl8366_smi *smi) +{ +	int ret; +	int i; + +	smi->mii_bus = mdiobus_alloc(); +	if (smi->mii_bus == NULL) { +		ret = -ENOMEM; +		goto err; +	} + +	spin_lock_init(&smi->lock); +	smi->mii_bus->priv = (void *) smi; +	smi->mii_bus->name = "rtl8366-smi"; +	smi->mii_bus->read = rtl8366_smi_mii_read; +	smi->mii_bus->write = rtl8366_smi_mii_write; +	snprintf(smi->mii_bus->id, MII_BUS_ID_SIZE, "%s", +			dev_name(&smi->pdev->dev)); +	smi->mii_bus->parent = &smi->pdev->dev; +	smi->mii_bus->phy_mask = ~(0x1f); +	smi->mii_bus->irq = smi->mii_irq; +	for (i = 0; i < PHY_MAX_ADDR; i++) +		smi->mii_irq[i] = PHY_POLL; + +	rtl8366_smi_dump_regs(smi); + +	ret = mdiobus_register(smi->mii_bus); +	if (ret) +		goto err_free; + +	rtl8366_smi_dump_regs(smi); + +	return 0; + + err_free: +	mdiobus_free(smi->mii_bus); + err: +	return ret; +} + +static void rtl8366_smi_mii_cleanup(struct rtl8366_smi *smi) +{ +	mdiobus_unregister(smi->mii_bus); +	mdiobus_free(smi->mii_bus); +} + +static int rtl8366_smi_setup(struct rtl8366_smi *smi) +{ +	u32 chip_id = 0; +	u32 chip_ver = 0; +	int ret; + +	ret = rtl8366_smi_read_reg(smi, RTL8366S_CHIP_ID_REG, &chip_id); +	if (ret) { +		dev_err(&smi->pdev->dev, "unable to read chip id\n"); +		return ret; +	} + +	switch (chip_id) { +	case RTL8366S_CHIP_ID_8366: +		break; +	default: +		dev_err(&smi->pdev->dev, "unknown chip id (%04x)\n", chip_id); +		return -ENODEV; +	} + +	ret = rtl8366_smi_read_reg(smi, RTL8366S_CHIP_VERSION_CTRL_REG, +				   &chip_ver); +	if (ret) { +		dev_err(&smi->pdev->dev, "unable to read chip version\n"); +		return ret; +	} + +	dev_info(&smi->pdev->dev, "RTL%04x ver. %u chip found\n", +		 chip_id, chip_ver & RTL8366S_CHIP_VERSION_MASK); + +	return 0; +} + +static int __init rtl8366_smi_probe(struct platform_device *pdev) +{ +	static int rtl8366_smi_version_printed; +	struct rtl8366_smi_platform_data *pdata; +	struct rtl8366_smi *smi; +	int err; + +	if (!rtl8366_smi_version_printed++) +		printk(KERN_NOTICE RTL8366_SMI_DRIVER_DESC +		       " version " RTL8366_SMI_DRIVER_VER"\n"); + +	pdata = pdev->dev.platform_data; +	if (!pdata) { +		dev_err(&pdev->dev, "no platform data specified\n"); +		err = -EINVAL; +		goto err_out; +	} + +	smi = kzalloc(sizeof(struct rtl8366_smi), GFP_KERNEL); +	if (!smi) { +		dev_err(&pdev->dev, "no memory for private data\n"); +		err = -ENOMEM; +		goto err_out; +	} + +	err = gpio_request(pdata->gpio_sda, dev_name(&pdev->dev)); +	if (err) { +		dev_err(&pdev->dev, "gpio_request failed for %u, err=%d\n", +			pdata->gpio_sda, err); +		goto err_free_smi; +	} + +	err = gpio_request(pdata->gpio_sck, dev_name(&pdev->dev)); +	if (err) { +		dev_err(&pdev->dev, "gpio_request failed for %u, err=%d\n", +			pdata->gpio_sck, err); +		goto err_free_sda; +	} + +	smi->pdev = pdev; +	smi->pdata = pdata; +	spin_lock_init(&smi->lock); + +	platform_set_drvdata(pdev, smi); + +	dev_info(&pdev->dev, "using GPIO pins %u (SDA) and %u (SCK)\n", +		 pdata->gpio_sda, pdata->gpio_sck); + +	err = rtl8366_smi_setup(smi); +	if (err) +		goto err_clear_drvdata; + +	err = rtl8366_smi_mii_init(smi); +	if (err) +		goto err_clear_drvdata; + +	return 0; + + err_clear_drvdata: +	platform_set_drvdata(pdev, NULL); +	gpio_free(pdata->gpio_sck); + err_free_sda: +	gpio_free(pdata->gpio_sda); + err_free_smi: +	kfree(smi); + err_out: +	return err; +} + +static int __devexit rtl8366_smi_remove(struct platform_device *pdev) +{ +	struct rtl8366_smi *smi = platform_get_drvdata(pdev); + +	if (smi) { +		struct rtl8366_smi_platform_data *pdata; + +		pdata = pdev->dev.platform_data; + +		rtl8366_smi_mii_cleanup(smi); +		platform_set_drvdata(pdev, NULL); +		gpio_free(pdata->gpio_sck); +		gpio_free(pdata->gpio_sda); +		kfree(smi); +	} + +	return 0; +} + +int rtl8366_phy_config_aneg(struct phy_device *phydev) +{ +	return 0; +} + +static struct platform_driver rtl8366_smi_driver = { +	.driver = { +		.name		= RTL8366_SMI_DRIVER_NAME, +		.owner		= THIS_MODULE, +	}, +	.probe		= rtl8366_smi_probe, +	.remove		= __devexit_p(rtl8366_smi_remove), +}; + +static struct phy_driver rtl8366_smi_phy_driver = { +	.phy_id		= 0x001cc960, +	.name		= "Realtek RTL8366", +	.phy_id_mask	= 0x1ffffff0, +	.features	= PHY_GBIT_FEATURES, +	.config_aneg	= rtl8366_phy_config_aneg, +	.read_status	= genphy_read_status, +	.driver		= { +		.owner = THIS_MODULE, +	}, +}; + +static int __init rtl8366_smi_init(void) +{ +	int ret; + +	ret = phy_driver_register(&rtl8366_smi_phy_driver); +	if (ret) +		return ret; + +	ret = platform_driver_register(&rtl8366_smi_driver); +	if (ret) +		goto err_phy_unregister; + +	return 0; + + err_phy_unregister: +	phy_driver_unregister(&rtl8366_smi_phy_driver); +	return ret; +} +module_init(rtl8366_smi_init); + +static void __exit rtl8366_smi_exit(void) +{ +	platform_driver_unregister(&rtl8366_smi_driver); +	phy_driver_unregister(&rtl8366_smi_phy_driver); +} +module_exit(rtl8366_smi_exit); + +MODULE_DESCRIPTION(RTL8366_SMI_DRIVER_DESC); +MODULE_VERSION(RTL8366_SMI_DRIVER_VER); +MODULE_AUTHOR("Gabor Juhos <juhosg@openwrt.org>"); +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:" RTL8366_SMI_DRIVER_NAME); diff --git a/target/linux/ar71xx/files/include/linux/rtl8366_smi.h b/target/linux/ar71xx/files/include/linux/rtl8366_smi.h new file mode 100644 index 000000000..cd0fcbc45 --- /dev/null +++ b/target/linux/ar71xx/files/include/linux/rtl8366_smi.h @@ -0,0 +1,19 @@ +/* + * Platform data definition for the Realtek RTL8366 ethernet switch driver + * + * Copyright (C) 2009 Gabor Juhos <juhosg@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 _RTL8366_SMI_H +#define _RTL8366_SMI_H + +struct rtl8366_smi_platform_data { +	unsigned	gpio_sda; +	unsigned	gpio_sck; +}; + +#endif /*  _RTL8366_SMI_H */ diff --git a/target/linux/ar71xx/patches-2.6.28/204-rtl8366-smi-driver.patch b/target/linux/ar71xx/patches-2.6.28/204-rtl8366-smi-driver.patch new file mode 100644 index 000000000..afb3cbdb7 --- /dev/null +++ b/target/linux/ar71xx/patches-2.6.28/204-rtl8366-smi-driver.patch @@ -0,0 +1,21 @@ +--- a/drivers/net/phy/Kconfig ++++ b/drivers/net/phy/Kconfig +@@ -114,4 +114,8 @@ config MDIO_OF_GPIO + 	---help--- + 	  Supports GPIO lib-based MDIO busses. +  ++config RTL8366_SMI ++	tristate "Support for RTL8366 switch via SMI interface" ++	depends on GENERIC_GPIO ++ + endif # PHYLIB +--- a/drivers/net/phy/Makefile ++++ b/drivers/net/phy/Makefile +@@ -17,6 +17,7 @@ obj-$(CONFIG_ADM6996_PHY)	+= adm6996.o + obj-$(CONFIG_IP175C_PHY)	+= ip175c.o + obj-$(CONFIG_RTL8306_PHY)	+= rtl8306.o + obj-$(CONFIG_REALTEK_PHY)	+= realtek.o ++obj-$(CONFIG_RTL8366_SMI)	+= rtl8366_smi.o + obj-$(CONFIG_MICREL_PHY)	+= micrel.o + obj-$(CONFIG_FIXED_PHY)		+= fixed.o + obj-$(CONFIG_MDIO_BITBANG)	+= mdio-bitbang.o diff --git a/target/linux/ar71xx/patches-2.6.30/204-rtl8366-smi-driver.patch b/target/linux/ar71xx/patches-2.6.30/204-rtl8366-smi-driver.patch new file mode 100644 index 000000000..77874b49f --- /dev/null +++ b/target/linux/ar71xx/patches-2.6.30/204-rtl8366-smi-driver.patch @@ -0,0 +1,21 @@ +--- a/drivers/net/phy/Kconfig ++++ b/drivers/net/phy/Kconfig +@@ -140,4 +140,8 @@ config MDIO_GPIO + 	  To compile this driver as a module, choose M here: the module + 	  will be called mdio-gpio. +  ++config RTL8366_SMI ++	tristate "Support for RTL8366 switch via SMI interface" ++	depends on GENERIC_GPIO ++ + endif # PHYLIB +--- a/drivers/net/phy/Makefile ++++ b/drivers/net/phy/Makefile +@@ -19,6 +19,7 @@ obj-$(CONFIG_IP175C_PHY)	+= ip175c.o + obj-$(CONFIG_REALTEK_PHY)	+= realtek.o + obj-$(CONFIG_AR8216_PHY)	+= ar8216.o + obj-$(CONFIG_RTL8306_PHY)	+= rtl8306.o ++obj-$(CONFIG_RTL8366_SMI)	+= rtl8366_smi.o + obj-$(CONFIG_LSI_ET1011C_PHY)	+= et1011c.o + obj-$(CONFIG_MICREL)		+= micrel.o + obj-$(CONFIG_FIXED_PHY)		+= fixed.o diff --git a/target/linux/ar71xx/patches-2.6.31/204-rtl8366-smi-driver.patch b/target/linux/ar71xx/patches-2.6.31/204-rtl8366-smi-driver.patch new file mode 100644 index 000000000..77874b49f --- /dev/null +++ b/target/linux/ar71xx/patches-2.6.31/204-rtl8366-smi-driver.patch @@ -0,0 +1,21 @@ +--- a/drivers/net/phy/Kconfig ++++ b/drivers/net/phy/Kconfig +@@ -140,4 +140,8 @@ config MDIO_GPIO + 	  To compile this driver as a module, choose M here: the module + 	  will be called mdio-gpio. +  ++config RTL8366_SMI ++	tristate "Support for RTL8366 switch via SMI interface" ++	depends on GENERIC_GPIO ++ + endif # PHYLIB +--- a/drivers/net/phy/Makefile ++++ b/drivers/net/phy/Makefile +@@ -19,6 +19,7 @@ obj-$(CONFIG_IP175C_PHY)	+= ip175c.o + obj-$(CONFIG_REALTEK_PHY)	+= realtek.o + obj-$(CONFIG_AR8216_PHY)	+= ar8216.o + obj-$(CONFIG_RTL8306_PHY)	+= rtl8306.o ++obj-$(CONFIG_RTL8366_SMI)	+= rtl8366_smi.o + obj-$(CONFIG_LSI_ET1011C_PHY)	+= et1011c.o + obj-$(CONFIG_MICREL)		+= micrel.o + obj-$(CONFIG_FIXED_PHY)		+= fixed.o diff --git a/target/linux/ar71xx/patches-2.6.32/204-rtl8366-smi-driver.patch b/target/linux/ar71xx/patches-2.6.32/204-rtl8366-smi-driver.patch new file mode 100644 index 000000000..78ec2e44c --- /dev/null +++ b/target/linux/ar71xx/patches-2.6.32/204-rtl8366-smi-driver.patch @@ -0,0 +1,21 @@ +--- a/drivers/net/phy/Kconfig ++++ b/drivers/net/phy/Kconfig +@@ -146,4 +146,8 @@ config MDIO_GPIO + 	  To compile this driver as a module, choose M here: the module + 	  will be called mdio-gpio. +  ++config RTL8366_SMI ++	tristate "Support for RTL8366 switch via SMI interface" ++	depends on GENERIC_GPIO ++ + endif # PHYLIB +--- a/drivers/net/phy/Makefile ++++ b/drivers/net/phy/Makefile +@@ -20,6 +20,7 @@ obj-$(CONFIG_IP175C_PHY)	+= ip175c.o + obj-$(CONFIG_REALTEK_PHY)	+= realtek.o + obj-$(CONFIG_AR8216_PHY)	+= ar8216.o + obj-$(CONFIG_RTL8306_PHY)	+= rtl8306.o ++obj-$(CONFIG_RTL8366_SMI)	+= rtl8366_smi.o + obj-$(CONFIG_LSI_ET1011C_PHY)	+= et1011c.o + obj-$(CONFIG_MICREL)		+= micrel.o + obj-$(CONFIG_FIXED_PHY)		+= fixed.o  | 
