diff --git a/target/linux/generic/files/drivers/net/phy/rtl8366_smi.c b/target/linux/generic/files/drivers/net/phy/rtl8366_smi.c index b8cdf30de48c..7df5527b409f 100644 --- a/target/linux/generic/files/drivers/net/phy/rtl8366_smi.c +++ b/target/linux/generic/files/drivers/net/phy/rtl8366_smi.c @@ -2,6 +2,7 @@ * Realtek RTL8366 SMI interface driver * * Copyright (C) 2009-2010 Gabor Juhos + * Copyright (C) 2017 Vitaly Chekryzhev <13hakta@gmail.com> * * 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 @@ -18,6 +19,7 @@ #include #include #include +#include #include #include @@ -27,16 +29,6 @@ #include "rtl8366_smi.h" -#define RTL8366_SMI_ACK_RETRY_COUNT 5 - -#define RTL8366_SMI_HW_STOP_DELAY 25 /* msecs */ -#define RTL8366_SMI_HW_START_DELAY 100 /* msecs */ - -static inline void rtl8366_smi_clk_delay(struct rtl8366_smi *smi) -{ - ndelay(smi->clk_delay); -} - static void rtl8366_smi_start(struct rtl8366_smi *smi) { unsigned int sda = smi->gpio_sda; @@ -207,34 +199,70 @@ int rtl8366_smi_read_reg(struct rtl8366_smi *smi, u32 addr, u32 *data) spin_lock_irqsave(&smi->lock, flags); - rtl8366_smi_start(smi); + if (smi->mdio_enabled) { + /* Write Start command to register 29 */ + smi->mii_bus->write(smi->mii_bus, RTL_MDIO_PHYID, + MDC_MDIO_START_REG, MDC_MDIO_START_OP); - /* send READ command */ - ret = rtl8366_smi_write_byte(smi, smi->cmd_read); - if (ret) - goto out; + /* Write address control code to register 31 */ + smi->mii_bus->write(smi->mii_bus, RTL_MDIO_PHYID, + MDC_MDIO_CTRL0_REG, MDC_MDIO_ADDR_OP); - /* set ADDR[7:0] */ - ret = rtl8366_smi_write_byte(smi, addr & 0xff); - if (ret) - goto out; + /* Write Start command to register 29 */ + smi->mii_bus->write(smi->mii_bus, RTL_MDIO_PHYID, + MDC_MDIO_START_REG, MDC_MDIO_START_OP); - /* set ADDR[15:8] */ - ret = rtl8366_smi_write_byte(smi, addr >> 8); - if (ret) - goto out; + /* Write address to register 23 */ + smi->mii_bus->write(smi->mii_bus, RTL_MDIO_PHYID, + MDC_MDIO_ADDRESS_REG, addr); - /* read DATA[7:0] */ - rtl8366_smi_read_byte0(smi, &lo); - /* read DATA[15:8] */ - rtl8366_smi_read_byte1(smi, &hi); + /* Write Start command to register 29 */ + smi->mii_bus->write(smi->mii_bus, RTL_MDIO_PHYID, + MDC_MDIO_START_REG, MDC_MDIO_START_OP); - *data = ((u32) lo) | (((u32) hi) << 8); + /* Write read control code to register 21 */ + smi->mii_bus->write(smi->mii_bus, RTL_MDIO_PHYID, + MDC_MDIO_CTRL1_REG, MDC_MDIO_READ_OP); - ret = 0; + /* Write Start command to register 29 */ + smi->mii_bus->write(smi->mii_bus, RTL_MDIO_PHYID, + MDC_MDIO_START_REG, MDC_MDIO_START_OP); + + /* Read data from register 25 */ + *data = smi->mii_bus->read(smi->mii_bus, RTL_MDIO_PHYID, + MDC_MDIO_DATA_READ_REG); + + ret = (*data == 0xffff) ? 1 : 0; + } else { + rtl8366_smi_start(smi); + + /* send READ command */ + ret = rtl8366_smi_write_byte(smi, smi->cmd_read); + 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); + } - out: - rtl8366_smi_stop(smi); spin_unlock_irqrestore(&smi->lock, flags); return ret; @@ -249,40 +277,77 @@ static int __rtl8366_smi_write_reg(struct rtl8366_smi *smi, spin_lock_irqsave(&smi->lock, flags); - rtl8366_smi_start(smi); + if (smi->mdio_enabled) { + /* Write Start command to register 29 */ + smi->mii_bus->write(smi->mii_bus, RTL_MDIO_PHYID, + MDC_MDIO_START_REG, MDC_MDIO_START_OP); - /* send WRITE command */ - ret = rtl8366_smi_write_byte(smi, smi->cmd_write); - if (ret) - goto out; + /* Write address control code to register 31 */ + smi->mii_bus->write(smi->mii_bus, RTL_MDIO_PHYID, + MDC_MDIO_CTRL0_REG, MDC_MDIO_ADDR_OP); - /* set ADDR[7:0] */ - ret = rtl8366_smi_write_byte(smi, addr & 0xff); - if (ret) - goto out; + /* Write Start command to register 29 */ + smi->mii_bus->write(smi->mii_bus, RTL_MDIO_PHYID, + MDC_MDIO_START_REG, MDC_MDIO_START_OP); - /* set ADDR[15:8] */ - ret = rtl8366_smi_write_byte(smi, addr >> 8); - if (ret) - goto out; + /* Write address to register 23 */ + smi->mii_bus->write(smi->mii_bus, RTL_MDIO_PHYID, + MDC_MDIO_ADDRESS_REG, addr); - /* write DATA[7:0] */ - ret = rtl8366_smi_write_byte(smi, data & 0xff); - if (ret) - goto out; + /* Write Start command to register 29 */ + smi->mii_bus->write(smi->mii_bus, RTL_MDIO_PHYID, + MDC_MDIO_START_REG, MDC_MDIO_START_OP); - /* write DATA[15:8] */ - if (ack) - ret = rtl8366_smi_write_byte(smi, data >> 8); - else - ret = rtl8366_smi_write_byte_noack(smi, data >> 8); - if (ret) - goto out; + /* Write data to register 24 */ + smi->mii_bus->write(smi->mii_bus, RTL_MDIO_PHYID, + MDC_MDIO_DATA_WRITE_REG, data); + + /* Write Start command to register 29 */ + smi->mii_bus->write(smi->mii_bus, RTL_MDIO_PHYID, + MDC_MDIO_START_REG, MDC_MDIO_START_OP); + + /* Write data control code to register 21 */ + smi->mii_bus->write(smi->mii_bus, RTL_MDIO_PHYID, + MDC_MDIO_CTRL1_REG, MDC_MDIO_WRITE_OP); + + ret = 0; + } else { + rtl8366_smi_start(smi); + + /* send WRITE command */ + ret = rtl8366_smi_write_byte(smi, smi->cmd_write); + 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] */ + if (ack) + ret = rtl8366_smi_write_byte(smi, data >> 8); + else + ret = rtl8366_smi_write_byte_noack(smi, data >> 8); + if (ret) + goto out; - ret = 0; + ret = 0; + +out: + rtl8366_smi_stop(smi); + } - out: - rtl8366_smi_stop(smi); spin_unlock_irqrestore(&smi->lock, flags); return ret; @@ -468,9 +533,12 @@ static int rtl8366_set_pvid(struct rtl8366_smi *smi, unsigned port, if (!used) { /* Update the entry from the 4K table */ + dev_info(smi->parent, "get VLAN 4K vid:%d\n", vid); err = smi->ops->get_vlan_4k(smi, vid, &vlan4k); - if (err) + if (err) { + dev_err(smi->parent, "PVID #%d vid:%d\n", err, vid); return err; + } vlanmc.vid = vid; vlanmc.member = vlan4k.member; @@ -591,9 +659,11 @@ static int rtl8366_init_vlan(struct rtl8366_smi *smi) if (err) return err; - err = rtl8366_set_pvid(smi, port, (port + 1)); - if (err) - return err; + if (port != smi->cpu_port) { + err = rtl8366_set_pvid(smi, port, (port + 1)); + if (err) + return err; + } } return rtl8366_enable_vlan(smi, 1); @@ -608,8 +678,8 @@ int rtl8366_debugfs_open(struct inode *inode, struct file *file) EXPORT_SYMBOL_GPL(rtl8366_debugfs_open); static ssize_t rtl8366_read_debugfs_vlan_mc(struct file *file, - char __user *user_buf, - size_t count, loff_t *ppos) + char __user *user_buf, + size_t count, loff_t *ppos) { struct rtl8366_smi *smi = (struct rtl8366_smi *)file->private_data; int i, len = 0; @@ -699,8 +769,8 @@ static ssize_t rtl8366_read_debugfs_pvid(struct file *file, } static ssize_t rtl8366_read_debugfs_reg(struct file *file, - char __user *user_buf, - size_t count, loff_t *ppos) + char __user *user_buf, + size_t count, loff_t *ppos) { struct rtl8366_smi *smi = (struct rtl8366_smi *)file->private_data; u32 t, reg = smi->dbg_reg; @@ -723,8 +793,8 @@ static ssize_t rtl8366_read_debugfs_reg(struct file *file, } static ssize_t rtl8366_write_debugfs_reg(struct file *file, - const char __user *user_buf, - size_t count, loff_t *ppos) + const char __user *user_buf, + size_t count, loff_t *ppos) { struct rtl8366_smi *smi = (struct rtl8366_smi *)file->private_data; unsigned long data; @@ -870,7 +940,7 @@ static void rtl8366_debugfs_init(struct rtl8366_smi *smi) } node = debugfs_create_u8("vlan_4k_page", S_IRUGO | S_IWUSR, root, - &smi->dbg_vlan_4k_page); + &smi->dbg_vlan_4k_page); if (!node) { dev_err(smi->parent, "Creating debugfs file '%s' failed\n", "vlan_4k_page"); @@ -915,6 +985,24 @@ static inline void rtl8366_debugfs_remove(struct rtl8366_smi *smi) {} static int rtl8366_smi_mii_init(struct rtl8366_smi *smi) { int ret; + int i; + struct mii_bus *bus; + struct device_node *np; + + if (smi->mdio_enabled) { + np = of_parse_phandle(smi->parent->of_node, "mdio", 0); + + if (np) { + bus = of_mdio_find_bus(np); + + if (bus) { + smi->mii_bus = bus; + return 0; + } else + return -EPROBE_DEFER; + } else + return -ENODEV; + } smi->mii_bus = mdiobus_alloc(); if (smi->mii_bus == NULL) { @@ -953,8 +1041,10 @@ static int rtl8366_smi_mii_init(struct rtl8366_smi *smi) static void rtl8366_smi_mii_cleanup(struct rtl8366_smi *smi) { - mdiobus_unregister(smi->mii_bus); - mdiobus_free(smi->mii_bus); + if (!smi->mdio_enabled) { + mdiobus_unregister(smi->mii_bus); + mdiobus_free(smi->mii_bus); + } } int rtl8366_sw_reset_switch(struct switch_dev *dev) @@ -1242,21 +1332,23 @@ static int __rtl8366_smi_init(struct rtl8366_smi *smi, const char *name) { int err; - err = gpio_request(smi->gpio_sda, name); - if (err) { - printk(KERN_ERR "rtl8366_smi: gpio_request failed for %u, err=%d\n", - smi->gpio_sda, err); - goto err_out; - } + if (!smi->mdio_enabled) { + err = gpio_request(smi->gpio_sda, name); + if (err) { + printk(KERN_ERR "rtl8366_smi: gpio_request failed for %u, err=%d\n", + smi->gpio_sda, err); + goto err_out; + } - err = gpio_request(smi->gpio_sck, name); - if (err) { - printk(KERN_ERR "rtl8366_smi: gpio_request failed for %u, err=%d\n", - smi->gpio_sck, err); - goto err_free_sda; - } + err = gpio_request(smi->gpio_sck, name); + if (err) { + printk(KERN_ERR "rtl8366_smi: gpio_request failed for %u, err=%d\n", + smi->gpio_sck, err); + goto err_free_sda; + } - spin_lock_init(&smi->lock); + spin_lock_init(&smi->lock); + } /* start the switch */ if (smi->hw_reset) { @@ -1277,8 +1369,10 @@ static void __rtl8366_smi_cleanup(struct rtl8366_smi *smi) if (smi->hw_reset) smi->hw_reset(true); - gpio_free(smi->gpio_sck); - gpio_free(smi->gpio_sda); + if (!smi->mdio_enabled) { + gpio_free(smi->gpio_sck); + gpio_free(smi->gpio_sda); + } } enum rtl8366_type rtl8366_smi_detect(struct rtl8366_platform_data *pdata) @@ -1331,8 +1425,15 @@ int rtl8366_smi_init(struct rtl8366_smi *smi) if (err) goto err_out; - dev_info(smi->parent, "using GPIO pins %u (SDA) and %u (SCK)\n", - smi->gpio_sda, smi->gpio_sck); + err = rtl8366_smi_mii_init(smi); + if (err) + goto err_free_sck; + + if (smi->mdio_enabled) + dev_info(smi->parent, "using bus %s\n", smi->mii_bus->name); + else + dev_info(smi->parent, "using GPIO pins %u (SDA) and %u (SCK)\n", + smi->gpio_sda, smi->gpio_sck); err = smi->ops->detect(smi); if (err) { @@ -1361,10 +1462,6 @@ int rtl8366_smi_init(struct rtl8366_smi *smi) if (err) goto err_free_sck; - err = rtl8366_smi_mii_init(smi); - if (err) - goto err_free_sck; - rtl8366_debugfs_init(smi); return 0; @@ -1387,16 +1484,20 @@ EXPORT_SYMBOL_GPL(rtl8366_smi_cleanup); #ifdef CONFIG_OF int rtl8366_smi_probe_of(struct platform_device *pdev, struct rtl8366_smi *smi) { - int sck = of_get_named_gpio(pdev->dev.of_node, "gpio-sck", 0); - int sda = of_get_named_gpio(pdev->dev.of_node, "gpio-sda", 0); + smi->mdio_enabled = of_property_read_bool(pdev->dev.of_node, "mdio"); - if (!gpio_is_valid(sck) || !gpio_is_valid(sda)) { - dev_err(&pdev->dev, "gpios missing in devictree\n"); - return -EINVAL; - } + if (!smi->mdio_enabled) { + int sck = of_get_named_gpio(pdev->dev.of_node, "gpio-sck", 0); + int sda = of_get_named_gpio(pdev->dev.of_node, "gpio-sda", 0); - smi->gpio_sda = sda; - smi->gpio_sck = sck; + if (!gpio_is_valid(sck) || !gpio_is_valid(sda)) { + dev_err(&pdev->dev, "gpios missing in devictree\n"); + return -EINVAL; + } + + smi->gpio_sda = sda; + smi->gpio_sck = sck; + } return 0; } @@ -1416,6 +1517,7 @@ int rtl8366_smi_probe_plat(struct platform_device *pdev, struct rtl8366_smi *smi return -EINVAL; } + smi->mdio_enabled = false; smi->gpio_sda = pdata->gpio_sda; smi->gpio_sck = pdata->gpio_sck; smi->hw_reset = pdata->hw_reset; @@ -1423,7 +1525,6 @@ int rtl8366_smi_probe_plat(struct platform_device *pdev, struct rtl8366_smi *smi return 0; } - struct rtl8366_smi *rtl8366_smi_probe(struct platform_device *pdev) { struct rtl8366_smi *smi; diff --git a/target/linux/generic/files/drivers/net/phy/rtl8366_smi.h b/target/linux/generic/files/drivers/net/phy/rtl8366_smi.h index bd41385bed1a..bbf619ad1c17 100644 --- a/target/linux/generic/files/drivers/net/phy/rtl8366_smi.h +++ b/target/linux/generic/files/drivers/net/phy/rtl8366_smi.h @@ -15,6 +15,26 @@ #include #include +#define RTL_MDIO_PHYID 0 +#define MDC_MDIO_CTRL0_REG 31 +#define MDC_MDIO_START_REG 29 +#define MDC_MDIO_CTRL1_REG 21 +#define MDC_MDIO_ADDRESS_REG 23 +#define MDC_MDIO_DATA_WRITE_REG 24 +#define MDC_MDIO_DATA_READ_REG 25 + +#define MDC_MDIO_START_OP 0xFFFF +#define MDC_MDIO_ADDR_OP 0x000E +#define MDC_MDIO_READ_OP 0x0001 +#define MDC_MDIO_WRITE_OP 0x0003 + +#define RTL8366_SMI_ACK_RETRY_COUNT 5 + +#define RTL8366_SMI_HW_STOP_DELAY 25 /* msecs */ +#define RTL8366_SMI_HW_START_DELAY 100 /* msecs */ + +#define rtl8366_smi_clk_delay(smi) ndelay(smi->clk_delay) + struct rtl8366_smi_ops; struct rtl8366_vlan_ops; struct mii_bus; @@ -33,6 +53,7 @@ struct rtl8366_smi { struct device *parent; unsigned int gpio_sda; unsigned int gpio_sck; + bool mdio_enabled; void (*hw_reset)(bool active); unsigned int clk_delay; /* ns */ u8 cmd_read; @@ -41,6 +62,7 @@ struct rtl8366_smi { struct mii_bus *mii_bus; int mii_irq[PHY_MAX_ADDR]; struct switch_dev sw_dev; + unsigned int chip_ver; unsigned int cpu_port; unsigned int num_ports; diff --git a/target/linux/generic/files/drivers/net/phy/rtl8367b.c b/target/linux/generic/files/drivers/net/phy/rtl8367b.c index a73e35ed2d1c..ba903215ece9 100644 --- a/target/linux/generic/files/drivers/net/phy/rtl8367b.c +++ b/target/linux/generic/files/drivers/net/phy/rtl8367b.c @@ -2,6 +2,7 @@ * Platform driver for the Realtek RTL8367R-VB ethernet switches * * Copyright (C) 2012 Gabor Juhos + * Copyright (C) 2017 Vitaly Chekryzhev <13hakta@gmail.com> * * 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 @@ -22,6 +23,8 @@ #define RTL8367B_RESET_DELAY 1000 /* msecs*/ +#define RTL8367B_PHY_NO 5 +#define RTL8367B_PHY_MAX (RTL8367B_PHY_NO - 1) #define RTL8367B_PHY_ADDR_MAX 8 #define RTL8367B_PHY_REG_MAX 31 @@ -43,7 +46,7 @@ #define RTL8367B_TA_CTRL_REG 0x0500 /*GOOD*/ #define RTL8367B_TA_CTRL_SPA_SHIFT 8 #define RTL8367B_TA_CTRL_SPA_MASK 0x7 -#define RTL8367B_TA_CTRL_METHOD BIT(4)/*GOOD*/ +#define RTL8367B_TA_CTRL_METHOD BIT(4) /*GOOD*/ #define RTL8367B_TA_CTRL_CMD_SHIFT 3 #define RTL8367B_TA_CTRL_CMD_READ 0 #define RTL8367B_TA_CTRL_CMD_WRITE 1 @@ -59,12 +62,12 @@ ((RTL8367B_TA_CTRL_CMD_WRITE << RTL8367B_TA_CTRL_CMD_SHIFT) | \ RTL8367B_TA_CTRL_TABLE_CVLAN) -#define RTL8367B_TA_ADDR_REG 0x0501/*GOOD*/ -#define RTL8367B_TA_ADDR_MASK 0x3fff/*GOOD*/ +#define RTL8367B_TA_ADDR_REG 0x0501 /*GOOD*/ +#define RTL8367B_TA_ADDR_MASK 0x3fff /*GOOD*/ -#define RTL8367B_TA_LUT_REG 0x0502/*GOOD*/ +#define RTL8367B_TA_LUT_REG 0x0502 /*GOOD*/ -#define RTL8367B_TA_WRDATA_REG(_x) (0x0510 + (_x))/*GOOD*/ +#define RTL8367B_TA_WRDATA_REG(_x) (0x0510 + (_x)) /*GOOD*/ #define RTL8367B_TA_VLAN_NUM_WORDS 2 #define RTL8367B_TA_VLAN_VID_MASK RTL8367B_VID_MASK #define RTL8367B_TA_VLAN0_MEMBER_SHIFT 0 @@ -74,7 +77,7 @@ #define RTL8367B_TA_VLAN1_FID_SHIFT 0 #define RTL8367B_TA_VLAN1_FID_MASK RTL8367B_FID_MASK -#define RTL8367B_TA_RDDATA_REG(_x) (0x0520 + (_x))/*GOOD*/ +#define RTL8367B_TA_RDDATA_REG(_x) (0x0520 + (_x)) /*GOOD*/ #define RTL8367B_VLAN_PVID_CTRL_REG(_p) (0x0700 + (_p) / 2) /*GOOD*/ #define RTL8367B_VLAN_PVID_CTRL_MASK 0x1f /*GOOD*/ @@ -82,12 +85,12 @@ #define RTL8367B_VLAN_MC_BASE(_x) (0x0728 + (_x) * 4) /*GOOD*/ #define RTL8367B_VLAN_MC_NUM_WORDS 4 /*GOOD*/ -#define RTL8367B_VLAN_MC0_MEMBER_SHIFT 0/*GOOD*/ -#define RTL8367B_VLAN_MC0_MEMBER_MASK RTL8367B_MEMBER_MASK/*GOOD*/ -#define RTL8367B_VLAN_MC1_FID_SHIFT 0/*GOOD*/ -#define RTL8367B_VLAN_MC1_FID_MASK RTL8367B_FID_MASK/*GOOD*/ -#define RTL8367B_VLAN_MC3_EVID_SHIFT 0/*GOOD*/ -#define RTL8367B_VLAN_MC3_EVID_MASK RTL8367B_VID_MASK/*GOOD*/ +#define RTL8367B_VLAN_MC0_MEMBER_SHIFT 0 /*GOOD*/ +#define RTL8367B_VLAN_MC0_MEMBER_MASK RTL8367B_MEMBER_MASK /*GOOD*/ +#define RTL8367B_VLAN_MC1_FID_SHIFT 0 /*GOOD*/ +#define RTL8367B_VLAN_MC1_FID_MASK RTL8367B_FID_MASK /*GOOD*/ +#define RTL8367B_VLAN_MC3_EVID_SHIFT 0 /*GOOD*/ +#define RTL8367B_VLAN_MC3_EVID_MASK RTL8367B_VID_MASK /*GOOD*/ #define RTL8367B_VLAN_CTRL_REG 0x07a8 /*GOOD*/ #define RTL8367B_VLAN_CTRL_ENABLE BIT(0) @@ -108,8 +111,8 @@ #define RTL8367B_MIB_CTRL0_RESET_MASK BIT(1) /*GOOD*/ #define RTL8367B_MIB_CTRL0_BUSY_MASK BIT(0) /*GOOD*/ -#define RTL8367B_SWC0_REG 0x1200/*GOOD*/ -#define RTL8367B_SWC0_MAX_LENGTH_SHIFT 13/*GOOD*/ +#define RTL8367B_SWC0_REG 0x1200 /*GOOD*/ +#define RTL8367B_SWC0_MAX_LENGTH_SHIFT 13 /*GOOD*/ #define RTL8367B_SWC0_MAX_LENGTH(_x) ((_x) << 13) /*GOOD*/ #define RTL8367B_SWC0_MAX_LENGTH_MASK RTL8367B_SWC0_MAX_LENGTH(0x3) #define RTL8367B_SWC0_MAX_LENGTH_1522 RTL8367B_SWC0_MAX_LENGTH(0) @@ -117,39 +120,25 @@ #define RTL8367B_SWC0_MAX_LENGTH_1552 RTL8367B_SWC0_MAX_LENGTH(2) #define RTL8367B_SWC0_MAX_LENGTH_16000 RTL8367B_SWC0_MAX_LENGTH(3) -#define RTL8367B_CHIP_NUMBER_REG 0x1300/*GOOD*/ - -#define RTL8367B_CHIP_VER_REG 0x1301/*GOOD*/ -#define RTL8367B_CHIP_VER_RLVID_SHIFT 12/*GOOD*/ -#define RTL8367B_CHIP_VER_RLVID_MASK 0xf/*GOOD*/ -#define RTL8367B_CHIP_VER_MCID_SHIFT 8/*GOOD*/ -#define RTL8367B_CHIP_VER_MCID_MASK 0xf/*GOOD*/ -#define RTL8367B_CHIP_VER_BOID_SHIFT 4/*GOOD*/ -#define RTL8367B_CHIP_VER_BOID_MASK 0xf/*GOOD*/ -#define RTL8367B_CHIP_VER_AFE_SHIFT 0/*GOOD*/ -#define RTL8367B_CHIP_VER_AFE_MASK 0x1/*GOOD*/ - +#define RTL8367B_CHIP_NUMBER_REG 0x1300 /*GOOD*/ +#define RTL8367B_CHIP_VER_REG 0x1301 /*GOOD*/ #define RTL8367B_CHIP_MODE_REG 0x1302 -#define RTL8367B_CHIP_MODE_MASK 0x7 - -#define RTL8367B_CHIP_DEBUG0_REG 0x1303 -#define RTL8367B_CHIP_DEBUG0_DUMMY0(_x) BIT(8 + (_x)) - -#define RTL8367B_CHIP_DEBUG1_REG 0x1304 #define RTL8367B_DIS_REG 0x1305 +#define RTL8367B_DIS_REG_2 0x13c3 #define RTL8367B_DIS_SKIP_MII_RXER(_x) BIT(12 + (_x)) #define RTL8367B_DIS_RGMII_SHIFT(_x) (4 * (_x)) #define RTL8367B_DIS_RGMII_MASK 0x7 +#define RTL8367B_RGMII_MASK 0xF -#define RTL8367B_EXT_RGMXF_REG(_x) (0x1306 + (_x)) +#define RTL8367B_EXT_RGMXF_REG(_x) (0x1306 + (_x) + ((_x > 1)? 0xBD : 0)) #define RTL8367B_EXT_RGMXF_DUMMY0_SHIFT 5 #define RTL8367B_EXT_RGMXF_DUMMY0_MASK 0x7ff #define RTL8367B_EXT_RGMXF_TXDELAY_SHIFT 3 #define RTL8367B_EXT_RGMXF_TXDELAY_MASK 1 #define RTL8367B_EXT_RGMXF_RXDELAY_MASK 0x7 -#define RTL8367B_DI_FORCE_REG(_x) (0x1310 + (_x)) +#define RTL8367B_DI_FORCE_REG(_x) (0x1310 + (_x) + ((_x > 1)? 0xB2 : 0)) #define RTL8367B_DI_FORCE_MODE BIT(12) #define RTL8367B_DI_FORCE_NWAY BIT(7) #define RTL8367B_DI_FORCE_TXPAUSE BIT(6) @@ -161,26 +150,24 @@ #define RTL8367B_DI_FORCE_SPEED_100 1 #define RTL8367B_DI_FORCE_SPEED_1000 2 -#define RTL8367B_MAC_FORCE_REG(_x) (0x1312 + (_x)) - #define RTL8367B_CHIP_RESET_REG 0x1322 /*GOOD*/ #define RTL8367B_CHIP_RESET_SW BIT(1) /*GOOD*/ #define RTL8367B_CHIP_RESET_HW BIT(0) /*GOOD*/ #define RTL8367B_PORT_STATUS_REG(_p) (0x1352 + (_p)) /*GOOD*/ #define RTL8367B_PORT_STATUS_EN_1000_SPI BIT(11) /*GOOD*/ -#define RTL8367B_PORT_STATUS_EN_100_SPI BIT(10)/*GOOD*/ -#define RTL8367B_PORT_STATUS_NWAY_FAULT BIT(9)/*GOOD*/ -#define RTL8367B_PORT_STATUS_LINK_MASTER BIT(8)/*GOOD*/ -#define RTL8367B_PORT_STATUS_NWAY BIT(7)/*GOOD*/ -#define RTL8367B_PORT_STATUS_TXPAUSE BIT(6)/*GOOD*/ -#define RTL8367B_PORT_STATUS_RXPAUSE BIT(5)/*GOOD*/ -#define RTL8367B_PORT_STATUS_LINK BIT(4)/*GOOD*/ -#define RTL8367B_PORT_STATUS_DUPLEX BIT(2)/*GOOD*/ -#define RTL8367B_PORT_STATUS_SPEED_MASK 0x0003/*GOOD*/ -#define RTL8367B_PORT_STATUS_SPEED_10 0/*GOOD*/ -#define RTL8367B_PORT_STATUS_SPEED_100 1/*GOOD*/ -#define RTL8367B_PORT_STATUS_SPEED_1000 2/*GOOD*/ +#define RTL8367B_PORT_STATUS_EN_100_SPI BIT(10) /*GOOD*/ +#define RTL8367B_PORT_STATUS_NWAY_FAULT BIT(9) /*GOOD*/ +#define RTL8367B_PORT_STATUS_LINK_MASTER BIT(8) /*GOOD*/ +#define RTL8367B_PORT_STATUS_NWAY BIT(7) /*GOOD*/ +#define RTL8367B_PORT_STATUS_TXPAUSE BIT(6) /*GOOD*/ +#define RTL8367B_PORT_STATUS_RXPAUSE BIT(5) /*GOOD*/ +#define RTL8367B_PORT_STATUS_LINK BIT(4) /*GOOD*/ +#define RTL8367B_PORT_STATUS_DUPLEX BIT(2) /*GOOD*/ +#define RTL8367B_PORT_STATUS_SPEED_MASK 0x0003 /*GOOD*/ +#define RTL8367B_PORT_STATUS_SPEED_10 0 /*GOOD*/ +#define RTL8367B_PORT_STATUS_SPEED_100 1 /*GOOD*/ +#define RTL8367B_PORT_STATUS_SPEED_1000 2 /*GOOD*/ #define RTL8367B_RTL_MAGIC_ID_REG 0x13c2 #define RTL8367B_RTL_MAGIC_ID_VAL 0x0249 @@ -225,10 +212,34 @@ RTL8367B_PORT_3 | RTL8367B_PORT_4 | RTL8367B_PORT_E0 | \ RTL8367B_PORT_E1 | RTL8367B_PORT_E2) -#define RTL8367B_PORTS_ALL_BUT_CPU \ - (RTL8367B_PORT_0 | RTL8367B_PORT_1 | RTL8367B_PORT_2 | \ - RTL8367B_PORT_3 | RTL8367B_PORT_4 | RTL8367B_PORT_E1 | \ - RTL8367B_PORT_E2) +#define RTL8367B_PORT_ALL_EXTERNAL \ + (RTL8367B_PORT_0 | RTL8367B_PORT_1 | RTL8367B_PORT_2 | \ + RTL8367B_PORT_3 | RTL8367B_PORT_4) + +#define RTL8367B_REG_PHY_AD 0x130f +#define RTL8367B_PDN_PHY_OFFSET 5 +#define RTL8367B_PHY_PAGE_ADDRESS 0x1F + +#define RTL8367B_REG_LED_MODE 0x1b02 +#define RTL8367B_REG_LED_CONFIGURATION 0x1b03 +#define RTL8367B_REG_LED_SYS_CONFIG 0x1b00 +#define RTL8367B_REG_PARA_LED_IO_EN1 0x1b24 +#define RTL8367B_REG_SCAN0_LED_IO_EN 0x1b26 +#define RTL8367B_LED_CONFIG_SEL_OFFSET 14 +#define RTL8367B_LED_SERI_CLK_EN_OFFSET 0 +#define RTL8367B_LED_SELECT_OFFSET 0 +#define RTL8367B_LED_SERI_DATA_EN_OFFSET 1 +#define RTL8367B_LED0_CFG_MASK 0xF +#define RTL8367B_LED1_CFG_MASK 0xF0 +#define RTL8367B_LED2_CFG_MASK 0xF00 +#define RTL8367B_LEDGROUPNO 3 +#define RTL8367B_LEDGROUPMASK 0x7 +#define RTL8367B_SEL_LEDRATE_MASK 0xE + +#define RTL8367B_PHY_POWERSAVING_REG 21 +#define RTL8367B_PHY_POWERSAVING_OFFSET 12 +#define RTL8367B_PHY_POWERSAVING_MASK 0x1000 +#define RTL8367B_PHY_GREEN_OFFSET 6 struct rtl8367b_initval { u16 reg; @@ -320,220 +331,55 @@ rtl8367b_mib_counters[RTL8367B_NUM_MIB_COUNTERS] = { return err; \ } while (0) -static const struct rtl8367b_initval rtl8367r_vb_initvals_0[] = { - {0x1B03, 0x0876}, {0x1200, 0x7FC4}, {0x0301, 0x0026}, {0x1722, 0x0E14}, - {0x205F, 0x0002}, {0x2059, 0x1A00}, {0x205F, 0x0000}, {0x207F, 0x0002}, - {0x2077, 0x0000}, {0x2078, 0x0000}, {0x2079, 0x0000}, {0x207A, 0x0000}, - {0x207B, 0x0000}, {0x207F, 0x0000}, {0x205F, 0x0002}, {0x2053, 0x0000}, - {0x2054, 0x0000}, {0x2055, 0x0000}, {0x2056, 0x0000}, {0x2057, 0x0000}, - {0x205F, 0x0000}, {0x12A4, 0x110A}, {0x12A6, 0x150A}, {0x13F1, 0x0013}, - {0x13F4, 0x0010}, {0x13F5, 0x0000}, {0x0018, 0x0F00}, {0x0038, 0x0F00}, - {0x0058, 0x0F00}, {0x0078, 0x0F00}, {0x0098, 0x0F00}, {0x12B6, 0x0C02}, - {0x12B7, 0x030F}, {0x12B8, 0x11FF}, {0x12BC, 0x0004}, {0x1362, 0x0115}, - {0x1363, 0x0002}, {0x1363, 0x0000}, {0x133F, 0x0030}, {0x133E, 0x000E}, - {0x221F, 0x0007}, {0x221E, 0x002D}, {0x2218, 0xF030}, {0x221F, 0x0007}, - {0x221E, 0x0023}, {0x2216, 0x0005}, {0x2215, 0x00B9}, {0x2219, 0x0044}, - {0x2215, 0x00BA}, {0x2219, 0x0020}, {0x2215, 0x00BB}, {0x2219, 0x00C1}, - {0x2215, 0x0148}, {0x2219, 0x0096}, {0x2215, 0x016E}, {0x2219, 0x0026}, - {0x2216, 0x0000}, {0x2216, 0x0000}, {0x221E, 0x002D}, {0x2218, 0xF010}, - {0x221F, 0x0007}, {0x221E, 0x0020}, {0x2215, 0x0D00}, {0x221F, 0x0000}, - {0x221F, 0x0000}, {0x2217, 0x2160}, {0x221F, 0x0001}, {0x2210, 0xF25E}, - {0x221F, 0x0007}, {0x221E, 0x0042}, {0x2215, 0x0F00}, {0x2215, 0x0F00}, - {0x2216, 0x7408}, {0x2215, 0x0E00}, {0x2215, 0x0F00}, {0x2215, 0x0F01}, - {0x2216, 0x4000}, {0x2215, 0x0E01}, {0x2215, 0x0F01}, {0x2215, 0x0F02}, - {0x2216, 0x9400}, {0x2215, 0x0E02}, {0x2215, 0x0F02}, {0x2215, 0x0F03}, - {0x2216, 0x7408}, {0x2215, 0x0E03}, {0x2215, 0x0F03}, {0x2215, 0x0F04}, - {0x2216, 0x4008}, {0x2215, 0x0E04}, {0x2215, 0x0F04}, {0x2215, 0x0F05}, - {0x2216, 0x9400}, {0x2215, 0x0E05}, {0x2215, 0x0F05}, {0x2215, 0x0F06}, - {0x2216, 0x0803}, {0x2215, 0x0E06}, {0x2215, 0x0F06}, {0x2215, 0x0D00}, - {0x2215, 0x0100}, {0x221F, 0x0001}, {0x2210, 0xF05E}, {0x221F, 0x0000}, - {0x2217, 0x2100}, {0x221F, 0x0000}, {0x220D, 0x0003}, {0x220E, 0x0015}, - {0x220D, 0x4003}, {0x220E, 0x0006}, {0x221F, 0x0000}, {0x2200, 0x1340}, - {0x133F, 0x0010}, {0x12A0, 0x0058}, {0x12A1, 0x0058}, {0x133E, 0x000E}, - {0x133F, 0x0030}, {0x221F, 0x0000}, {0x2210, 0x0166}, {0x221F, 0x0000}, - {0x133E, 0x000E}, {0x133F, 0x0010}, {0x133F, 0x0030}, {0x133E, 0x000E}, - {0x221F, 0x0005}, {0x2205, 0xFFF6}, {0x2206, 0x0080}, {0x2205, 0x8B6E}, - {0x2206, 0x0000}, {0x220F, 0x0100}, {0x2205, 0x8000}, {0x2206, 0x0280}, - {0x2206, 0x28F7}, {0x2206, 0x00E0}, {0x2206, 0xFFF7}, {0x2206, 0xA080}, +#define REG_RD_PHY(_smi, _addr, _reg, _val) \ + REG_RD(_smi, RTL8367B_INTERNAL_PHY_REG(_addr, _reg), _val); + +#define REG_WR_PHY(_smi, _addr, _reg, _val) \ + REG_WR(_smi, RTL8367B_INTERNAL_PHY_REG(_addr, _reg), _val); + +static const struct rtl8367b_initval rtl8367rb_initvals[] = { + {0x1B03, 0x0876}, {0x1200, 0x7FC4}, {0x1305, 0xC000}, {0x121E, 0x03CA}, + {0x1233, 0x0352}, {0x1234, 0x0064}, {0x1237, 0x0096}, {0x1238, 0x0078}, + {0x1239, 0x0084}, {0x123A, 0x0030}, {0x205F, 0x0002}, {0x2059, 0x1A00}, + {0x205F, 0x0000}, {0x207F, 0x0002}, {0x2077, 0x0000}, {0x2078, 0x0000}, + {0x2079, 0x0000}, {0x207A, 0x0000}, {0x207B, 0x0000}, {0x207F, 0x0000}, + {0x205F, 0x0002}, {0x2053, 0x0000}, {0x2054, 0x0000}, {0x2055, 0x0000}, + {0x2056, 0x0000}, {0x2057, 0x0000}, {0x205F, 0x0000}, {0x133F, 0x0030}, + {0x133E, 0x000E}, {0x221F, 0x0005}, {0x2205, 0x8B86}, {0x2206, 0x800E}, + {0x221F, 0x0000}, {0x133F, 0x0010}, {0x12A3, 0x2200}, {0x6107, 0xE58B}, + {0x6103, 0xA970}, {0x0018, 0x0F00}, {0x0038, 0x0F00}, {0x0058, 0x0F00}, + {0x0078, 0x0F00}, {0x0098, 0x0F00}, {0x133F, 0x0030}, {0x133E, 0x000E}, + {0x221F, 0x0005}, {0x2205, 0x8B6E}, {0x2206, 0x0000}, {0x220F, 0x0100}, + {0x2205, 0xFFF6}, {0x2206, 0x0080}, {0x2205, 0x8000}, {0x2206, 0x0280}, + {0x2206, 0x2BF7}, {0x2206, 0x00E0}, {0x2206, 0xFFF7}, {0x2206, 0xA080}, {0x2206, 0x02AE}, {0x2206, 0xF602}, {0x2206, 0x0153}, {0x2206, 0x0201}, - {0x2206, 0x6602}, {0x2206, 0x80B9}, {0x2206, 0xE08B}, {0x2206, 0x8CE1}, - {0x2206, 0x8B8D}, {0x2206, 0x1E01}, {0x2206, 0xE18B}, {0x2206, 0x8E1E}, - {0x2206, 0x01A0}, {0x2206, 0x00E7}, {0x2206, 0xAEDB}, {0x2206, 0xEEE0}, - {0x2206, 0x120E}, {0x2206, 0xEEE0}, {0x2206, 0x1300}, {0x2206, 0xEEE0}, - {0x2206, 0x2001}, {0x2206, 0xEEE0}, {0x2206, 0x2166}, {0x2206, 0xEEE0}, - {0x2206, 0xC463}, {0x2206, 0xEEE0}, {0x2206, 0xC5E8}, {0x2206, 0xEEE0}, - {0x2206, 0xC699}, {0x2206, 0xEEE0}, {0x2206, 0xC7C2}, {0x2206, 0xEEE0}, - {0x2206, 0xC801}, {0x2206, 0xEEE0}, {0x2206, 0xC913}, {0x2206, 0xEEE0}, - {0x2206, 0xCA30}, {0x2206, 0xEEE0}, {0x2206, 0xCB3E}, {0x2206, 0xEEE0}, - {0x2206, 0xDCE1}, {0x2206, 0xEEE0}, {0x2206, 0xDD00}, {0x2206, 0xEEE2}, - {0x2206, 0x0001}, {0x2206, 0xEEE2}, {0x2206, 0x0100}, {0x2206, 0xEEE4}, - {0x2206, 0x8860}, {0x2206, 0xEEE4}, {0x2206, 0x8902}, {0x2206, 0xEEE4}, - {0x2206, 0x8C00}, {0x2206, 0xEEE4}, {0x2206, 0x8D30}, {0x2206, 0xEEEA}, - {0x2206, 0x1480}, {0x2206, 0xEEEA}, {0x2206, 0x1503}, {0x2206, 0xEEEA}, - {0x2206, 0xC600}, {0x2206, 0xEEEA}, {0x2206, 0xC706}, {0x2206, 0xEE85}, - {0x2206, 0xEE00}, {0x2206, 0xEE85}, {0x2206, 0xEF00}, {0x2206, 0xEE8B}, - {0x2206, 0x6750}, {0x2206, 0xEE8B}, {0x2206, 0x6632}, {0x2206, 0xEE8A}, - {0x2206, 0xD448}, {0x2206, 0xEE8A}, {0x2206, 0xD548}, {0x2206, 0xEE8A}, - {0x2206, 0xD649}, {0x2206, 0xEE8A}, {0x2206, 0xD7F8}, {0x2206, 0xEE8B}, - {0x2206, 0x85E2}, {0x2206, 0xEE8B}, {0x2206, 0x8700}, {0x2206, 0xEEFF}, - {0x2206, 0xF600}, {0x2206, 0xEEFF}, {0x2206, 0xF7FC}, {0x2206, 0x04F8}, - {0x2206, 0xE08B}, {0x2206, 0x8EAD}, {0x2206, 0x2023}, {0x2206, 0xF620}, - {0x2206, 0xE48B}, {0x2206, 0x8E02}, {0x2206, 0x2877}, {0x2206, 0x0225}, - {0x2206, 0xC702}, {0x2206, 0x26A1}, {0x2206, 0x0281}, {0x2206, 0xB302}, - {0x2206, 0x8496}, {0x2206, 0x0202}, {0x2206, 0xA102}, {0x2206, 0x27F1}, - {0x2206, 0x0228}, {0x2206, 0xF902}, {0x2206, 0x2AA0}, {0x2206, 0x0282}, - {0x2206, 0xB8E0}, {0x2206, 0x8B8E}, {0x2206, 0xAD21}, {0x2206, 0x08F6}, - {0x2206, 0x21E4}, {0x2206, 0x8B8E}, {0x2206, 0x0202}, {0x2206, 0x80E0}, - {0x2206, 0x8B8E}, {0x2206, 0xAD22}, {0x2206, 0x05F6}, {0x2206, 0x22E4}, - {0x2206, 0x8B8E}, {0x2206, 0xE08B}, {0x2206, 0x8EAD}, {0x2206, 0x2305}, - {0x2206, 0xF623}, {0x2206, 0xE48B}, {0x2206, 0x8EE0}, {0x2206, 0x8B8E}, - {0x2206, 0xAD24}, {0x2206, 0x08F6}, {0x2206, 0x24E4}, {0x2206, 0x8B8E}, - {0x2206, 0x0227}, {0x2206, 0x6AE0}, {0x2206, 0x8B8E}, {0x2206, 0xAD25}, - {0x2206, 0x05F6}, {0x2206, 0x25E4}, {0x2206, 0x8B8E}, {0x2206, 0xE08B}, - {0x2206, 0x8EAD}, {0x2206, 0x260B}, {0x2206, 0xF626}, {0x2206, 0xE48B}, - {0x2206, 0x8E02}, {0x2206, 0x830D}, {0x2206, 0x021D}, {0x2206, 0x6BE0}, - {0x2206, 0x8B8E}, {0x2206, 0xAD27}, {0x2206, 0x05F6}, {0x2206, 0x27E4}, - {0x2206, 0x8B8E}, {0x2206, 0x0281}, {0x2206, 0x4402}, {0x2206, 0x045C}, - {0x2206, 0xFC04}, {0x2206, 0xF8E0}, {0x2206, 0x8B83}, {0x2206, 0xAD23}, - {0x2206, 0x30E0}, {0x2206, 0xE022}, {0x2206, 0xE1E0}, {0x2206, 0x2359}, - {0x2206, 0x02E0}, {0x2206, 0x85EF}, {0x2206, 0xE585}, {0x2206, 0xEFAC}, - {0x2206, 0x2907}, {0x2206, 0x1F01}, {0x2206, 0x9E51}, {0x2206, 0xAD29}, - {0x2206, 0x20E0}, {0x2206, 0x8B83}, {0x2206, 0xAD21}, {0x2206, 0x06E1}, - {0x2206, 0x8B84}, {0x2206, 0xAD28}, {0x2206, 0x42E0}, {0x2206, 0x8B85}, - {0x2206, 0xAD21}, {0x2206, 0x06E1}, {0x2206, 0x8B84}, {0x2206, 0xAD29}, - {0x2206, 0x36BF}, {0x2206, 0x34BF}, {0x2206, 0x022C}, {0x2206, 0x31AE}, - {0x2206, 0x2EE0}, {0x2206, 0x8B83}, {0x2206, 0xAD21}, {0x2206, 0x10E0}, - {0x2206, 0x8B84}, {0x2206, 0xF620}, {0x2206, 0xE48B}, {0x2206, 0x84EE}, - {0x2206, 0x8ADA}, {0x2206, 0x00EE}, {0x2206, 0x8ADB}, {0x2206, 0x00E0}, - {0x2206, 0x8B85}, {0x2206, 0xAD21}, {0x2206, 0x0CE0}, {0x2206, 0x8B84}, - {0x2206, 0xF621}, {0x2206, 0xE48B}, {0x2206, 0x84EE}, {0x2206, 0x8B72}, - {0x2206, 0xFFBF}, {0x2206, 0x34C2}, {0x2206, 0x022C}, {0x2206, 0x31FC}, - {0x2206, 0x04F8}, {0x2206, 0xFAEF}, {0x2206, 0x69E0}, {0x2206, 0x8B85}, - {0x2206, 0xAD21}, {0x2206, 0x42E0}, {0x2206, 0xE022}, {0x2206, 0xE1E0}, - {0x2206, 0x2358}, {0x2206, 0xC059}, {0x2206, 0x021E}, {0x2206, 0x01E1}, - {0x2206, 0x8B72}, {0x2206, 0x1F10}, {0x2206, 0x9E2F}, {0x2206, 0xE48B}, - {0x2206, 0x72AD}, {0x2206, 0x2123}, {0x2206, 0xE18B}, {0x2206, 0x84F7}, - {0x2206, 0x29E5}, {0x2206, 0x8B84}, {0x2206, 0xAC27}, {0x2206, 0x10AC}, - {0x2206, 0x2605}, {0x2206, 0x0205}, {0x2206, 0x23AE}, {0x2206, 0x1602}, - {0x2206, 0x0535}, {0x2206, 0x0282}, {0x2206, 0x30AE}, {0x2206, 0x0E02}, - {0x2206, 0x056A}, {0x2206, 0x0282}, {0x2206, 0x75AE}, {0x2206, 0x0602}, - {0x2206, 0x04DC}, {0x2206, 0x0282}, {0x2206, 0x04EF}, {0x2206, 0x96FE}, - {0x2206, 0xFC04}, {0x2206, 0xF8F9}, {0x2206, 0xE08B}, {0x2206, 0x87AD}, - {0x2206, 0x2321}, {0x2206, 0xE0EA}, {0x2206, 0x14E1}, {0x2206, 0xEA15}, - {0x2206, 0xAD26}, {0x2206, 0x18F6}, {0x2206, 0x27E4}, {0x2206, 0xEA14}, - {0x2206, 0xE5EA}, {0x2206, 0x15F6}, {0x2206, 0x26E4}, {0x2206, 0xEA14}, - {0x2206, 0xE5EA}, {0x2206, 0x15F7}, {0x2206, 0x27E4}, {0x2206, 0xEA14}, - {0x2206, 0xE5EA}, {0x2206, 0x15FD}, {0x2206, 0xFC04}, {0x2206, 0xF8F9}, - {0x2206, 0xE08B}, {0x2206, 0x87AD}, {0x2206, 0x233A}, {0x2206, 0xAD22}, - {0x2206, 0x37E0}, {0x2206, 0xE020}, {0x2206, 0xE1E0}, {0x2206, 0x21AC}, - {0x2206, 0x212E}, {0x2206, 0xE0EA}, {0x2206, 0x14E1}, {0x2206, 0xEA15}, - {0x2206, 0xF627}, {0x2206, 0xE4EA}, {0x2206, 0x14E5}, {0x2206, 0xEA15}, - {0x2206, 0xE2EA}, {0x2206, 0x12E3}, {0x2206, 0xEA13}, {0x2206, 0x5A8F}, - {0x2206, 0x6A20}, {0x2206, 0xE6EA}, {0x2206, 0x12E7}, {0x2206, 0xEA13}, - {0x2206, 0xF726}, {0x2206, 0xE4EA}, {0x2206, 0x14E5}, {0x2206, 0xEA15}, - {0x2206, 0xF727}, {0x2206, 0xE4EA}, {0x2206, 0x14E5}, {0x2206, 0xEA15}, - {0x2206, 0xFDFC}, {0x2206, 0x04F8}, {0x2206, 0xF9E0}, {0x2206, 0x8B87}, - {0x2206, 0xAD23}, {0x2206, 0x38AD}, {0x2206, 0x2135}, {0x2206, 0xE0E0}, - {0x2206, 0x20E1}, {0x2206, 0xE021}, {0x2206, 0xAC21}, {0x2206, 0x2CE0}, - {0x2206, 0xEA14}, {0x2206, 0xE1EA}, {0x2206, 0x15F6}, {0x2206, 0x27E4}, - {0x2206, 0xEA14}, {0x2206, 0xE5EA}, {0x2206, 0x15E2}, {0x2206, 0xEA12}, - {0x2206, 0xE3EA}, {0x2206, 0x135A}, {0x2206, 0x8FE6}, {0x2206, 0xEA12}, - {0x2206, 0xE7EA}, {0x2206, 0x13F7}, {0x2206, 0x26E4}, {0x2206, 0xEA14}, - {0x2206, 0xE5EA}, {0x2206, 0x15F7}, {0x2206, 0x27E4}, {0x2206, 0xEA14}, - {0x2206, 0xE5EA}, {0x2206, 0x15FD}, {0x2206, 0xFC04}, {0x2206, 0xF8FA}, - {0x2206, 0xEF69}, {0x2206, 0xE08B}, {0x2206, 0x86AD}, {0x2206, 0x2146}, - {0x2206, 0xE0E0}, {0x2206, 0x22E1}, {0x2206, 0xE023}, {0x2206, 0x58C0}, - {0x2206, 0x5902}, {0x2206, 0x1E01}, {0x2206, 0xE18B}, {0x2206, 0x651F}, - {0x2206, 0x109E}, {0x2206, 0x33E4}, {0x2206, 0x8B65}, {0x2206, 0xAD21}, - {0x2206, 0x22AD}, {0x2206, 0x272A}, {0x2206, 0xD400}, {0x2206, 0x01BF}, - {0x2206, 0x34F2}, {0x2206, 0x022C}, {0x2206, 0xA2BF}, {0x2206, 0x34F5}, - {0x2206, 0x022C}, {0x2206, 0xE0E0}, {0x2206, 0x8B67}, {0x2206, 0x1B10}, - {0x2206, 0xAA14}, {0x2206, 0xE18B}, {0x2206, 0x660D}, {0x2206, 0x1459}, - {0x2206, 0x0FAE}, {0x2206, 0x05E1}, {0x2206, 0x8B66}, {0x2206, 0x590F}, - {0x2206, 0xBF85}, {0x2206, 0x6102}, {0x2206, 0x2CA2}, {0x2206, 0xEF96}, - {0x2206, 0xFEFC}, {0x2206, 0x04F8}, {0x2206, 0xF9FA}, {0x2206, 0xFBEF}, - {0x2206, 0x79E2}, {0x2206, 0x8AD2}, {0x2206, 0xAC19}, {0x2206, 0x2DE0}, - {0x2206, 0xE036}, {0x2206, 0xE1E0}, {0x2206, 0x37EF}, {0x2206, 0x311F}, - {0x2206, 0x325B}, {0x2206, 0x019E}, {0x2206, 0x1F7A}, {0x2206, 0x0159}, - {0x2206, 0x019F}, {0x2206, 0x0ABF}, {0x2206, 0x348E}, {0x2206, 0x022C}, - {0x2206, 0x31F6}, {0x2206, 0x06AE}, {0x2206, 0x0FF6}, {0x2206, 0x0302}, - {0x2206, 0x0470}, {0x2206, 0xF703}, {0x2206, 0xF706}, {0x2206, 0xBF34}, - {0x2206, 0x9302}, {0x2206, 0x2C31}, {0x2206, 0xAC1A}, {0x2206, 0x25E0}, - {0x2206, 0xE022}, {0x2206, 0xE1E0}, {0x2206, 0x23EF}, {0x2206, 0x300D}, - {0x2206, 0x311F}, {0x2206, 0x325B}, {0x2206, 0x029E}, {0x2206, 0x157A}, - {0x2206, 0x0258}, {0x2206, 0xC4A0}, {0x2206, 0x0408}, {0x2206, 0xBF34}, - {0x2206, 0x9E02}, {0x2206, 0x2C31}, {0x2206, 0xAE06}, {0x2206, 0xBF34}, - {0x2206, 0x9C02}, {0x2206, 0x2C31}, {0x2206, 0xAC1B}, {0x2206, 0x4AE0}, - {0x2206, 0xE012}, {0x2206, 0xE1E0}, {0x2206, 0x13EF}, {0x2206, 0x300D}, - {0x2206, 0x331F}, {0x2206, 0x325B}, {0x2206, 0x1C9E}, {0x2206, 0x3AEF}, - {0x2206, 0x325B}, {0x2206, 0x1C9F}, {0x2206, 0x09BF}, {0x2206, 0x3498}, - {0x2206, 0x022C}, {0x2206, 0x3102}, {0x2206, 0x83C5}, {0x2206, 0x5A03}, - {0x2206, 0x0D03}, {0x2206, 0x581C}, {0x2206, 0x1E20}, {0x2206, 0x0207}, - {0x2206, 0xA0A0}, {0x2206, 0x000E}, {0x2206, 0x0284}, {0x2206, 0x17AD}, - {0x2206, 0x1817}, {0x2206, 0xBF34}, {0x2206, 0x9A02}, {0x2206, 0x2C31}, - {0x2206, 0xAE0F}, {0x2206, 0xBF34}, {0x2206, 0xC802}, {0x2206, 0x2C31}, - {0x2206, 0xBF34}, {0x2206, 0xC502}, {0x2206, 0x2C31}, {0x2206, 0x0284}, - {0x2206, 0x52E6}, {0x2206, 0x8AD2}, {0x2206, 0xEF97}, {0x2206, 0xFFFE}, - {0x2206, 0xFDFC}, {0x2206, 0x04F8}, {0x2206, 0xBF34}, {0x2206, 0xDA02}, - {0x2206, 0x2CE0}, {0x2206, 0xE58A}, {0x2206, 0xD3BF}, {0x2206, 0x34D4}, - {0x2206, 0x022C}, {0x2206, 0xE00C}, {0x2206, 0x1159}, {0x2206, 0x02E0}, - {0x2206, 0x8AD3}, {0x2206, 0x1E01}, {0x2206, 0xE48A}, {0x2206, 0xD3D1}, - {0x2206, 0x00BF}, {0x2206, 0x34DA}, {0x2206, 0x022C}, {0x2206, 0xA2D1}, - {0x2206, 0x01BF}, {0x2206, 0x34D4}, {0x2206, 0x022C}, {0x2206, 0xA2BF}, - {0x2206, 0x34CB}, {0x2206, 0x022C}, {0x2206, 0xE0E5}, {0x2206, 0x8ACE}, - {0x2206, 0xBF85}, {0x2206, 0x6702}, {0x2206, 0x2CE0}, {0x2206, 0xE58A}, - {0x2206, 0xCFBF}, {0x2206, 0x8564}, {0x2206, 0x022C}, {0x2206, 0xE0E5}, - {0x2206, 0x8AD0}, {0x2206, 0xBF85}, {0x2206, 0x6A02}, {0x2206, 0x2CE0}, - {0x2206, 0xE58A}, {0x2206, 0xD1FC}, {0x2206, 0x04F8}, {0x2206, 0xE18A}, - {0x2206, 0xD1BF}, {0x2206, 0x856A}, {0x2206, 0x022C}, {0x2206, 0xA2E1}, - {0x2206, 0x8AD0}, {0x2206, 0xBF85}, {0x2206, 0x6402}, {0x2206, 0x2CA2}, - {0x2206, 0xE18A}, {0x2206, 0xCFBF}, {0x2206, 0x8567}, {0x2206, 0x022C}, - {0x2206, 0xA2E1}, {0x2206, 0x8ACE}, {0x2206, 0xBF34}, {0x2206, 0xCB02}, - {0x2206, 0x2CA2}, {0x2206, 0xE18A}, {0x2206, 0xD3BF}, {0x2206, 0x34DA}, - {0x2206, 0x022C}, {0x2206, 0xA2E1}, {0x2206, 0x8AD3}, {0x2206, 0x0D11}, - {0x2206, 0xBF34}, {0x2206, 0xD402}, {0x2206, 0x2CA2}, {0x2206, 0xFC04}, - {0x2206, 0xF9A0}, {0x2206, 0x0405}, {0x2206, 0xE38A}, {0x2206, 0xD4AE}, - {0x2206, 0x13A0}, {0x2206, 0x0805}, {0x2206, 0xE38A}, {0x2206, 0xD5AE}, - {0x2206, 0x0BA0}, {0x2206, 0x0C05}, {0x2206, 0xE38A}, {0x2206, 0xD6AE}, - {0x2206, 0x03E3}, {0x2206, 0x8AD7}, {0x2206, 0xEF13}, {0x2206, 0xBF34}, - {0x2206, 0xCB02}, {0x2206, 0x2CA2}, {0x2206, 0xEF13}, {0x2206, 0x0D11}, - {0x2206, 0xBF85}, {0x2206, 0x6702}, {0x2206, 0x2CA2}, {0x2206, 0xEF13}, - {0x2206, 0x0D14}, {0x2206, 0xBF85}, {0x2206, 0x6402}, {0x2206, 0x2CA2}, - {0x2206, 0xEF13}, {0x2206, 0x0D17}, {0x2206, 0xBF85}, {0x2206, 0x6A02}, - {0x2206, 0x2CA2}, {0x2206, 0xFD04}, {0x2206, 0xF8E0}, {0x2206, 0x8B85}, - {0x2206, 0xAD27}, {0x2206, 0x2DE0}, {0x2206, 0xE036}, {0x2206, 0xE1E0}, - {0x2206, 0x37E1}, {0x2206, 0x8B73}, {0x2206, 0x1F10}, {0x2206, 0x9E20}, - {0x2206, 0xE48B}, {0x2206, 0x73AC}, {0x2206, 0x200B}, {0x2206, 0xAC21}, - {0x2206, 0x0DAC}, {0x2206, 0x250F}, {0x2206, 0xAC27}, {0x2206, 0x0EAE}, - {0x2206, 0x0F02}, {0x2206, 0x84CC}, {0x2206, 0xAE0A}, {0x2206, 0x0284}, - {0x2206, 0xD1AE}, {0x2206, 0x05AE}, {0x2206, 0x0302}, {0x2206, 0x84D8}, - {0x2206, 0xFC04}, {0x2206, 0xEE8B}, {0x2206, 0x6800}, {0x2206, 0x0402}, - {0x2206, 0x84E5}, {0x2206, 0x0285}, {0x2206, 0x2804}, {0x2206, 0x0285}, - {0x2206, 0x4904}, {0x2206, 0xEE8B}, {0x2206, 0x6800}, {0x2206, 0xEE8B}, - {0x2206, 0x6902}, {0x2206, 0x04F8}, {0x2206, 0xF9E0}, {0x2206, 0x8B85}, - {0x2206, 0xAD26}, {0x2206, 0x38D0}, {0x2206, 0x0B02}, {0x2206, 0x2B4D}, - {0x2206, 0x5882}, {0x2206, 0x7882}, {0x2206, 0x9F2D}, {0x2206, 0xE08B}, - {0x2206, 0x68E1}, {0x2206, 0x8B69}, {0x2206, 0x1F10}, {0x2206, 0x9EC8}, - {0x2206, 0x10E4}, {0x2206, 0x8B68}, {0x2206, 0xE0E0}, {0x2206, 0x00E1}, - {0x2206, 0xE001}, {0x2206, 0xF727}, {0x2206, 0xE4E0}, {0x2206, 0x00E5}, - {0x2206, 0xE001}, {0x2206, 0xE2E0}, {0x2206, 0x20E3}, {0x2206, 0xE021}, - {0x2206, 0xAD30}, {0x2206, 0xF7F6}, {0x2206, 0x27E4}, {0x2206, 0xE000}, - {0x2206, 0xE5E0}, {0x2206, 0x01FD}, {0x2206, 0xFC04}, {0x2206, 0xF8FA}, - {0x2206, 0xEF69}, {0x2206, 0xE08B}, {0x2206, 0x86AD}, {0x2206, 0x2212}, - {0x2206, 0xE0E0}, {0x2206, 0x14E1}, {0x2206, 0xE015}, {0x2206, 0xAD26}, - {0x2206, 0x9CE1}, {0x2206, 0x85E0}, {0x2206, 0xBF85}, {0x2206, 0x6D02}, - {0x2206, 0x2CA2}, {0x2206, 0xEF96}, {0x2206, 0xFEFC}, {0x2206, 0x04F8}, - {0x2206, 0xFAEF}, {0x2206, 0x69E0}, {0x2206, 0x8B86}, {0x2206, 0xAD22}, - {0x2206, 0x09E1}, {0x2206, 0x85E1}, {0x2206, 0xBF85}, {0x2206, 0x6D02}, - {0x2206, 0x2CA2}, {0x2206, 0xEF96}, {0x2206, 0xFEFC}, {0x2206, 0x0464}, - {0x2206, 0xE48C}, {0x2206, 0xFDE4}, {0x2206, 0x80CA}, {0x2206, 0xE480}, - {0x2206, 0x66E0}, {0x2206, 0x8E70}, {0x2206, 0xE076}, {0x2205, 0xE142}, - {0x2206, 0x0701}, {0x2205, 0xE140}, {0x2206, 0x0405}, {0x220F, 0x0000}, - {0x221F, 0x0000}, {0x2200, 0x1340}, {0x133E, 0x000E}, {0x133F, 0x0010}, - {0x13EB, 0x11BB} + {0x2206, 0x6602}, {0x2206, 0x8044}, {0x2206, 0x0201}, {0x2206, 0x7CE0}, + {0x2206, 0x8B8C}, {0x2206, 0xE18B}, {0x2206, 0x8D1E}, {0x2206, 0x01E1}, + {0x2206, 0x8B8E}, {0x2206, 0x1E01}, {0x2206, 0xA000}, {0x2206, 0xE4AE}, + {0x2206, 0xD8EE}, {0x2206, 0x85C0}, {0x2206, 0x00EE}, {0x2206, 0x85C1}, + {0x2206, 0x00EE}, {0x2206, 0x8AFC}, {0x2206, 0x07EE}, {0x2206, 0x8AFD}, + {0x2206, 0x73EE}, {0x2206, 0xFFF6}, {0x2206, 0x00EE}, {0x2206, 0xFFF7}, + {0x2206, 0xFC04}, {0x2206, 0xF8E0}, {0x2206, 0x8B8E}, {0x2206, 0xAD20}, + {0x2206, 0x0302}, {0x2206, 0x8050}, {0x2206, 0xFC04}, {0x2206, 0xF8F9}, + {0x2206, 0xE08B}, {0x2206, 0x85AD}, {0x2206, 0x2548}, {0x2206, 0xE08A}, + {0x2206, 0xE4E1}, {0x2206, 0x8AE5}, {0x2206, 0x7C00}, {0x2206, 0x009E}, + {0x2206, 0x35EE}, {0x2206, 0x8AE4}, {0x2206, 0x00EE}, {0x2206, 0x8AE5}, + {0x2206, 0x00E0}, {0x2206, 0x8AFC}, {0x2206, 0xE18A}, {0x2206, 0xFDE2}, + {0x2206, 0x85C0}, {0x2206, 0xE385}, {0x2206, 0xC102}, {0x2206, 0x2DAC}, + {0x2206, 0xAD20}, {0x2206, 0x12EE}, {0x2206, 0x8AE4}, {0x2206, 0x03EE}, + {0x2206, 0x8AE5}, {0x2206, 0xB7EE}, {0x2206, 0x85C0}, {0x2206, 0x00EE}, + {0x2206, 0x85C1}, {0x2206, 0x00AE}, {0x2206, 0x1115}, {0x2206, 0xE685}, + {0x2206, 0xC0E7}, {0x2206, 0x85C1}, {0x2206, 0xAE08}, {0x2206, 0xEE85}, + {0x2206, 0xC000}, {0x2206, 0xEE85}, {0x2206, 0xC100}, {0x2206, 0xFDFC}, + {0x2206, 0x0400}, {0x2205, 0xE142}, {0x2206, 0x0701}, {0x2205, 0xE140}, + {0x2206, 0x0405}, {0x220F, 0x0000}, {0x221F, 0x0000}, {0x133E, 0x000E}, + {0x133F, 0x0010}, {0x13E0, 0x0010}, {0x207F, 0x0002}, {0x2073, 0x1D22}, + {0x207F, 0x0000}, {0x133F, 0x0030}, {0x133E, 0x000E}, {0x2200, 0x1340}, + {0x133E, 0x000E}, {0x133F, 0x0010}, {0x1303, 0x0778}, {0x1304, 0x7777}, + {0x13E2, 0x01FE} }; -static const struct rtl8367b_initval rtl8367r_vb_initvals_1[] = { +static const struct rtl8367b_initval rtl8367r_vb_initvals[] = { {0x1B03, 0x0876}, {0x1200, 0x7FC4}, {0x1305, 0xC000}, {0x121E, 0x03CA}, {0x1233, 0x0352}, {0x1234, 0x0064}, {0x1237, 0x0096}, {0x1238, 0x0078}, {0x1239, 0x0084}, {0x123A, 0x0030}, {0x205F, 0x0002}, {0x2059, 0x1A00}, @@ -571,12 +417,13 @@ static const struct rtl8367b_initval rtl8367r_vb_initvals_1[] = { {0x2206, 0x0405}, {0x220F, 0x0000}, {0x221F, 0x0000}, {0x133E, 0x000E}, {0x133F, 0x0010}, {0x13EB, 0x11BB}, {0x207F, 0x0002}, {0x2073, 0x1D22}, {0x207F, 0x0000}, {0x133F, 0x0030}, {0x133E, 0x000E}, {0x2200, 0x1340}, - {0x133E, 0x000E}, {0x133F, 0x0010}, + {0x133E, 0x000E}, {0x133F, 0x0010}, {0x1303, 0x0778}, {0x1304, 0x7777}, + {0x13E2, 0x01FE} }; static int rtl8367b_write_initvals(struct rtl8366_smi *smi, - const struct rtl8367b_initval *initvals, - int count) + const struct rtl8367b_initval *initvals, + int count) { int err; int i; @@ -588,7 +435,7 @@ static int rtl8367b_write_initvals(struct rtl8366_smi *smi, } static int rtl8367b_read_phy_reg(struct rtl8366_smi *smi, - u32 phy_addr, u32 phy_reg, u32 *val) + u32 phy_addr, u32 phy_reg, u32 *val) { int timeout; u32 data; @@ -635,7 +482,7 @@ static int rtl8367b_read_phy_reg(struct rtl8366_smi *smi, } static int rtl8367b_write_phy_reg(struct rtl8366_smi *smi, - u32 phy_addr, u32 phy_reg, u32 val) + u32 phy_addr, u32 phy_reg, u32 val) { int timeout; u32 data; @@ -682,34 +529,61 @@ static int rtl8367b_write_phy_reg(struct rtl8366_smi *smi, return 0; } -static int rtl8367b_init_regs(struct rtl8366_smi *smi) +static int rtl8367b_port_phy_reg_set( + struct rtl8366_smi *smi, + u32 phy_addr, u32 phy_reg, u32 value) { - const struct rtl8367b_initval *initvals; - u32 chip_ver; - u32 rlvid; - int count; int err; - REG_WR(smi, RTL8367B_RTL_MAGIC_ID_REG, RTL8367B_RTL_MAGIC_ID_VAL); - REG_RD(smi, RTL8367B_CHIP_VER_REG, &chip_ver); + if (phy_addr > RTL8367B_PHY_ADDR_MAX) + return -EINVAL; - rlvid = (chip_ver >> RTL8367B_CHIP_VER_RLVID_SHIFT) & - RTL8367B_CHIP_VER_RLVID_MASK; + if (phy_reg > RTL8367B_PHY_REG_MAX) + return -EINVAL; - switch (rlvid) { - case 0: - initvals = rtl8367r_vb_initvals_0; - count = ARRAY_SIZE(rtl8367r_vb_initvals_0); - break; + REG_WR_PHY(smi, phy_addr, RTL8367B_PHY_PAGE_ADDRESS, 0); + REG_WR_PHY(smi, phy_addr, phy_reg, value); - case 1: - initvals = rtl8367r_vb_initvals_1; - count = ARRAY_SIZE(rtl8367r_vb_initvals_1); - break; + return 0; +} - default: - dev_err(smi->parent, "unknow rlvid %u\n", rlvid); - return -ENODEV; +static int rtl8367b_port_phy_reg_get( + struct rtl8366_smi *smi, + u32 phy_addr, u32 phy_reg, u32 *value) +{ + int err; + + if (phy_addr > RTL8367B_PHY_ADDR_MAX) + return -EINVAL; + + if (phy_reg > RTL8367B_PHY_REG_MAX) + return -EINVAL; + + REG_WR_PHY(smi, phy_addr, RTL8367B_PHY_PAGE_ADDRESS, 0); + REG_RD_PHY(smi, phy_addr, phy_reg, value); + + return 0; +} + +static int rtl8367b_init_regs(struct rtl8366_smi *smi) +{ + const struct rtl8367b_initval *initvals; + int count; + + switch (smi->chip_ver) { + case 0x1000: + initvals = rtl8367rb_initvals; + count = ARRAY_SIZE(rtl8367rb_initvals); + break; + + case 0x1010: + initvals = rtl8367r_vb_initvals; + count = ARRAY_SIZE(rtl8367r_vb_initvals); + break; + + default: + dev_err(smi->parent, "unknown chip %u\n", smi->chip_ver); + return -ENODEV; } /* TODO: disable RLTP */ @@ -747,44 +621,25 @@ static int rtl8367b_extif_set_mode(struct rtl8366_smi *smi, int id, { int err; - /* set port mode */ - switch (mode) { - case RTL8367_EXTIF_MODE_RGMII: - case RTL8367_EXTIF_MODE_RGMII_33V: - REG_WR(smi, RTL8367B_CHIP_DEBUG0_REG, 0x0367); - REG_WR(smi, RTL8367B_CHIP_DEBUG1_REG, 0x7777); - break; - - case RTL8367_EXTIF_MODE_TMII_MAC: - case RTL8367_EXTIF_MODE_TMII_PHY: - REG_RMW(smi, RTL8367B_BYPASS_LINE_RATE_REG, - BIT((id + 1) % 2), BIT((id + 1) % 2)); - break; - - case RTL8367_EXTIF_MODE_GMII: - REG_RMW(smi, RTL8367B_CHIP_DEBUG0_REG, - RTL8367B_CHIP_DEBUG0_DUMMY0(id), - RTL8367B_CHIP_DEBUG0_DUMMY0(id)); + if (mode == RTL8367_EXTIF_MODE_GMII) REG_RMW(smi, RTL8367B_EXT_RGMXF_REG(id), BIT(6), BIT(6)); - break; - - case RTL8367_EXTIF_MODE_MII_MAC: - case RTL8367_EXTIF_MODE_MII_PHY: - case RTL8367_EXTIF_MODE_DISABLED: - REG_RMW(smi, RTL8367B_BYPASS_LINE_RATE_REG, - BIT((id + 1) % 2), 0); - REG_RMW(smi, RTL8367B_EXT_RGMXF_REG(id), BIT(6), 0); - break; - - default: - dev_err(smi->parent, - "invalid mode for external interface %d\n", id); - return -EINVAL; - } + else + if ((mode == RTL8367_EXTIF_MODE_TMII_MAC) || + (mode == RTL8367_EXTIF_MODE_TMII_PHY)) + REG_RMW(smi, RTL8367B_BYPASS_LINE_RATE_REG, + BIT(id % 2), BIT(id % 2)); + else { + REG_RMW(smi, RTL8367B_BYPASS_LINE_RATE_REG, BIT(id), 0); + REG_RMW(smi, RTL8367B_EXT_RGMXF_REG(id), BIT(6), 0); + } - REG_RMW(smi, RTL8367B_DIS_REG, - RTL8367B_DIS_RGMII_MASK << RTL8367B_DIS_RGMII_SHIFT(id), - mode << RTL8367B_DIS_RGMII_SHIFT(id)); + if (id == 0 || id == 1) + REG_RMW(smi, RTL8367B_DIS_REG, + RTL8367B_DIS_RGMII_MASK << RTL8367B_DIS_RGMII_SHIFT(id), + mode << RTL8367B_DIS_RGMII_SHIFT(id)); + else + if (id == 2) + REG_RMW(smi, RTL8367B_DIS_REG_2, RTL8367B_RGMII_MASK, mode); return 0; } @@ -818,7 +673,7 @@ static int rtl8367b_extif_set_force(struct rtl8366_smi *smi, int id, } static int rtl8367b_extif_set_rgmii_delay(struct rtl8366_smi *smi, int id, - unsigned txdelay, unsigned rxdelay) + unsigned txdelay, unsigned rxdelay) { u32 mask; u32 val; @@ -844,6 +699,10 @@ static int rtl8367b_extif_init(struct rtl8366_smi *smi, int id, mode = (cfg) ? cfg->mode : RTL8367_EXTIF_MODE_DISABLED; + /* Map external port ID. V-RB has ext ports: 0,1; RB: 1,2 */ + if (smi->chip_ver == 0x1000) + id++; + err = rtl8367b_extif_set_mode(smi, id, mode); if (err) return err; @@ -857,6 +716,8 @@ static int rtl8367b_extif_init(struct rtl8366_smi *smi, int id, cfg->rxdelay); if (err) return err; + + smi->cpu_port = RTL8367B_CPU_PORT_NUM + id; } return 0; @@ -907,6 +768,86 @@ static int rtl8367b_extif_init_of(struct rtl8366_smi *smi, int id, } #endif +static int rtl8367b_led_group_enable(struct rtl8366_smi *smi, u32 group) +{ + return rtl8366_smi_rmwr(smi, + RTL8367B_REG_PARA_LED_IO_EN1 + group / 2, + 0xFF << ((group % 2) * 8), RTL8367B_PORT_ALL_EXTERNAL); +} + +/* Set serial/parallel led mode */ +static int rtl8367b_led_op_mode(struct rtl8366_smi *smi, u32 mode) +{ + int err; + + /* Invalid input parameter */ + if (mode > 1) + return -EINVAL; + + /* Set parallel mode */ + err = rtl8366_smi_rmwr(smi, RTL8367B_REG_LED_SYS_CONFIG, BIT(RTL8367B_LED_SELECT_OFFSET), mode); + if (err) return err; + + /* Disable serial CLK mode */ + err = rtl8366_smi_rmwr(smi, RTL8367B_REG_SCAN0_LED_IO_EN, BIT(RTL8367B_LED_SERI_CLK_EN_OFFSET), mode); + if (err) return err; + + /* Disable serial DATA mode */ + err = rtl8366_smi_rmwr(smi, + RTL8367B_REG_SCAN0_LED_IO_EN, + BIT(RTL8367B_LED_SERI_DATA_EN_OFFSET), + mode << RTL8367B_LED_SERI_DATA_EN_OFFSET); + if (err) return err; + + return 0; +} + +static int rtl8367b_led_group_set_mode(struct rtl8366_smi *smi, + u32 group, u32 mode) +{ + int err; + + if(group > 2) + return -EINVAL; + + if(mode > 15) + return -EINVAL; + + /* Switch off bit */ + err = rtl8366_smi_rmwr(smi, + RTL8367B_REG_LED_CONFIGURATION, + BIT(RTL8367B_LED_CONFIG_SEL_OFFSET), 0); + if (err) return err; + + return rtl8366_smi_rmwr(smi, RTL8367B_REG_LED_CONFIGURATION, + 0xF << (4 * group), + mode << (4 * group)); +} + +static int rtl8367b_set_led_blinkrate(struct rtl8366_smi *smi, u32 blinkRate) +{ + int err; + + if (blinkRate > 7) + return -EINVAL; + + REG_RMW(smi, RTL8367B_REG_LED_MODE, RTL8367B_SEL_LEDRATE_MASK, blinkRate); + + return 0; +} + +static int rtl8367b_get_led_blinkrate(struct rtl8366_smi *smi, u32 *blinkRate) +{ + int err; + + err = rtl8366_smi_read_reg(smi, RTL8367B_REG_LED_MODE, blinkRate); + if (err) return err; + + *blinkRate = *blinkRate & RTL8367B_SEL_LEDRATE_MASK; + + return 0; +} + static int rtl8367b_setup(struct rtl8366_smi *smi) { struct rtl8367_platform_data *pdata; @@ -942,6 +883,9 @@ static int rtl8367b_setup(struct rtl8366_smi *smi) REG_RMW(smi, RTL8367B_SWC0_REG, RTL8367B_SWC0_MAX_LENGTH_MASK, RTL8367B_SWC0_MAX_LENGTH_1536); + /* enable all PHY (if disabled by bootstrap) */ + REG_RMW(smi, RTL8367B_REG_PHY_AD, BIT(RTL8367B_PDN_PHY_OFFSET), 0); + /* * discard VLAN tagged packets if the port is not a member of * the VLAN with which the packets is associated. @@ -959,6 +903,17 @@ static int rtl8367b_setup(struct rtl8366_smi *smi) RTL8367B_PORT_MISC_CFG_EGRESS_MODE_ORIGINAL << RTL8367B_PORT_MISC_CFG_EGRESS_MODE_SHIFT); + /* setup LEDs */ + err = rtl8367b_led_group_enable(smi, 0); + if (err) return err; + + /* Set led to parallel mode */ + err = rtl8367b_led_op_mode(smi, 0); + if (err) return err; + + err = rtl8367b_led_group_set_mode(smi, 0, 2); + if (err) return err; + return 0; } @@ -1122,7 +1077,7 @@ static int rtl8367b_set_vlan_mc(struct rtl8366_smi *smi, u32 index, RTL8367B_VLAN_MC1_FID_SHIFT; data[2] = 0; data[3] = (vlanmc->vid & RTL8367B_VLAN_MC3_EVID_MASK) << - RTL8367B_VLAN_MC3_EVID_SHIFT; + RTL8367B_VLAN_MC3_EVID_SHIFT; for (i = 0; i < ARRAY_SIZE(data); i++) REG_WR(smi, RTL8367B_VLAN_MC_BASE(index) + i, data[i]); @@ -1151,6 +1106,17 @@ static int rtl8367b_set_mc_index(struct rtl8366_smi *smi, int port, int index) if (port >= RTL8367B_NUM_PORTS || index >= RTL8367B_NUM_VLANS) return -EINVAL; + // Skip nonexistent ports + switch (smi->chip_ver) { + case 0x1000: + if (port == 5) return 0; + break; + + case 0x1010: + if (port == 7) return 0; + break; + } + return rtl8366_smi_rmwr(smi, RTL8367B_VLAN_PVID_CTRL_REG(port), RTL8367B_VLAN_PVID_CTRL_MASK << RTL8367B_VLAN_PVID_CTRL_SHIFT(port), @@ -1186,10 +1152,25 @@ static int rtl8367b_is_vlan_valid(struct rtl8366_smi *smi, unsigned vlan) static int rtl8367b_enable_port(struct rtl8366_smi *smi, int port, int enable) { int err; + u32 data; + + dev_dbg(smi->parent, "port #%d set %s\n", port + 1, (enable == 1)? "on" : "off"); + /* Port isolation */ REG_WR(smi, RTL8367B_PORT_ISOLATION_REG(port), (enable) ? RTL8367B_PORTS_ALL : 0); + /* Power up/down port */ + err = rtl8367b_port_phy_reg_get(smi, port, 0, &data); + if (err == 0) { + if (enable) + data &= ~(1U << 11); + else + data |= (1U << 11); + + rtl8367b_port_phy_reg_set(smi, port, 0, data); + } + return 0; } @@ -1204,8 +1185,8 @@ static int rtl8367b_sw_reset_mibs(struct switch_dev *dev, } static int rtl8367b_sw_get_port_link(struct switch_dev *dev, - int port, - struct switch_port_link *link) + int port, + struct switch_port_link *link) { struct rtl8366_smi *smi = sw_to_rtl8366_smi(dev); u32 data = 0; @@ -1245,8 +1226,8 @@ static int rtl8367b_sw_get_port_link(struct switch_dev *dev, } static int rtl8367b_sw_get_max_length(struct switch_dev *dev, - const struct switch_attr *attr, - struct switch_val *val) + const struct switch_attr *attr, + struct switch_val *val) { struct rtl8366_smi *smi = sw_to_rtl8366_smi(dev); u32 data; @@ -1259,8 +1240,8 @@ static int rtl8367b_sw_get_max_length(struct switch_dev *dev, } static int rtl8367b_sw_set_max_length(struct switch_dev *dev, - const struct switch_attr *attr, - struct switch_val *val) + const struct switch_attr *attr, + struct switch_val *val) { struct rtl8366_smi *smi = sw_to_rtl8366_smi(dev); u32 max_len; @@ -1286,6 +1267,104 @@ static int rtl8367b_sw_set_max_length(struct switch_dev *dev, RTL8367B_SWC0_MAX_LENGTH_MASK, max_len); } +static int rtl8367b_sw_get_led_blink(struct switch_dev *dev, + const struct switch_attr *attr, + struct switch_val *val) +{ + struct rtl8366_smi *smi = sw_to_rtl8366_smi(dev); + u32 data; + + if (rtl8367b_get_led_blinkrate(smi, &data)) + return -EIO; + + val->value.i = data; + + return 0; +} + +static int rtl8367b_sw_set_led_blink(struct switch_dev *dev, + const struct switch_attr *attr, + struct switch_val *val) +{ + struct rtl8366_smi *smi = sw_to_rtl8366_smi(dev); + + if (val->value.i > 15) + return -EINVAL; + + return rtl8367b_set_led_blinkrate(smi, val->value.i); +} + +static int rtl8367b_sw_get_led(struct switch_dev *dev, + const struct switch_attr *attr, + struct switch_val *val) +{ + struct rtl8366_smi *smi = sw_to_rtl8366_smi(dev); + u32 data; + + rtl8366_smi_read_reg(smi, RTL8367B_REG_LED_CONFIGURATION, &data); + val->value.i = data & 0xF; + + return 0; +} + +static int rtl8367b_sw_set_led(struct switch_dev *dev, + const struct switch_attr *attr, + struct switch_val *val) +{ + struct rtl8366_smi *smi = sw_to_rtl8366_smi(dev); + + if (val->value.i > 15) + return -EINVAL; + + return rtl8367b_led_group_set_mode(smi, 0, val->value.i); +} + +static int rtl8367b_sw_get_green(struct switch_dev *dev, + const struct switch_attr *attr, + struct switch_val *val) +{ + u32 data; + int err; + + struct rtl8366_smi *smi = sw_to_rtl8366_smi(dev); + + /* Read green flag */ + REG_RD(smi, RTL8367B_REG_PHY_AD, &data); + + val->value.i = ((data & BIT(RTL8367B_PHY_GREEN_OFFSET)) >> RTL8367B_PHY_GREEN_OFFSET == 1)? 1 : 0; + + return 0; +} + +static int rtl8367b_sw_set_green(struct switch_dev *dev, + const struct switch_attr *attr, + struct switch_val *val) +{ + int i, err; + u32 data; + + struct rtl8366_smi *smi = sw_to_rtl8366_smi(dev); + + if (val->value.i > 1) + return -EINVAL; + + REG_RMW(smi, + RTL8367B_REG_PHY_AD, + BIT(RTL8367B_PHY_GREEN_OFFSET), + val->value.i << RTL8367B_PHY_GREEN_OFFSET); + + /* Set green mode for all PHY ports */ + for (i = 0; i < RTL8367B_PHY_MAX; i++) { + rtl8367b_port_phy_reg_get(smi, i, RTL8367B_PHY_POWERSAVING_REG, &data); + + data = (data & (~RTL8367B_PHY_POWERSAVING_MASK)) | (val->value.i << + RTL8367B_PHY_POWERSAVING_OFFSET); + + rtl8367b_port_phy_reg_set(smi, i, RTL8367B_PHY_POWERSAVING_REG, data); + } + + return 0; +} static int rtl8367b_sw_reset_port_mibs(struct switch_dev *dev, const struct switch_attr *attr, @@ -1302,6 +1381,37 @@ static int rtl8367b_sw_reset_port_mibs(struct switch_dev *dev, RTL8367B_MIB_CTRL0_PORT_RESET_MASK(port % 8)); } +static int rtl8367b_sw_set_port_disable(struct switch_dev *dev, + const struct switch_attr *attr, + struct switch_val *val) +{ + if (val->port_vlan > RTL8367B_PHY_MAX) + return -EINVAL; + + struct rtl8366_smi *smi = sw_to_rtl8366_smi(dev); + + return rtl8367b_enable_port(smi, val->port_vlan, 1 - val->value.i); +} + +static int rtl8367b_sw_get_port_disable(struct switch_dev *dev, + const struct switch_attr *attr, + struct switch_val *val) +{ + int err; + u32 data; + + struct rtl8366_smi *smi = sw_to_rtl8366_smi(dev); + + if (val->port_vlan > RTL8367B_PHY_MAX) + return -EINVAL; + + err = rtl8367b_port_phy_reg_get(smi, val->port_vlan, 0, &data); + + val->value.i = ((data & (1 << 11)) >> 11); + + return 0; +} + static struct switch_attr rtl8367b_globals[] = { { .type = SWITCH_TYPE_INT, @@ -1332,7 +1442,28 @@ static struct switch_attr rtl8367b_globals[] = { .set = rtl8367b_sw_set_max_length, .get = rtl8367b_sw_get_max_length, .max = 3, - } + }, { + .type = SWITCH_TYPE_INT, + .name = "led", + .description = "Set LED mode led (0 - disable)", + .get = rtl8367b_sw_get_led, + .set = rtl8367b_sw_set_led, + .max = 15, + }, { + .type = SWITCH_TYPE_INT, + .name = "blink", + .description = "Set LED blink rate (0:43ms, 1:84ms, 2:120ms, 3:170ms, 4:340ms, 5:670ms)", + .get = rtl8367b_sw_get_led_blink, + .set = rtl8367b_sw_set_led_blink, + .max = 7, + }, { + .type = SWITCH_TYPE_INT, + .name = "green", + .description = "Set green mode (0 - disable)", + .get = rtl8367b_sw_get_green, + .set = rtl8367b_sw_set_green, + .max = 1, + }, }; static struct switch_attr rtl8367b_port[] = { @@ -1348,6 +1479,13 @@ static struct switch_attr rtl8367b_port[] = { .max = 33, .set = NULL, .get = rtl8366_sw_get_port_mib, + }, { + .type = SWITCH_TYPE_INT, + .name = "disable", + .description = "Get/Set port state (enabled or disabled)", + .max = 1, + .set = rtl8367b_sw_set_port_disable, + .get = rtl8367b_sw_get_port_disable, }, }; @@ -1390,7 +1528,7 @@ static int rtl8367b_switch_init(struct rtl8366_smi *smi) int err; dev->name = "RTL8367B"; - dev->cpu_port = RTL8367B_CPU_PORT_NUM; + dev->cpu_port = smi->cpu_port; dev->ports = RTL8367B_NUM_PORTS; dev->vlans = RTL8367B_NUM_VIDS; dev->ops = &rtl8367b_sw_ops; @@ -1443,41 +1581,28 @@ static int rtl8367b_detect(struct rtl8366_smi *smi) u32 chip_num; u32 chip_ver; u32 chip_mode; - int ret; - - /* TODO: improve chip detection */ - rtl8366_smi_write_reg(smi, RTL8367B_RTL_MAGIC_ID_REG, - RTL8367B_RTL_MAGIC_ID_VAL); + int err; - ret = rtl8366_smi_read_reg(smi, RTL8367B_CHIP_NUMBER_REG, &chip_num); - if (ret) { - dev_err(smi->parent, "unable to read %s register\n", - "chip number"); - return ret; - } + REG_WR(smi, RTL8367B_RTL_MAGIC_ID_REG, RTL8367B_RTL_MAGIC_ID_VAL); - ret = rtl8366_smi_read_reg(smi, RTL8367B_CHIP_VER_REG, &chip_ver); - if (ret) { + err = rtl8366_smi_read_reg(smi, RTL8367B_CHIP_VER_REG, &chip_ver); + if (err) { dev_err(smi->parent, "unable to read %s register\n", "chip version"); - return ret; - } - - ret = rtl8366_smi_read_reg(smi, RTL8367B_CHIP_MODE_REG, &chip_mode); - if (ret) { - dev_err(smi->parent, "unable to read %s register\n", - "chip mode"); - return ret; + return err; } switch (chip_ver) { - case 0x1000: - chip_name = "8367RB"; - break; - case 0x1010: - chip_name = "8367R-VB"; - break; + case 0x1000: + chip_name = "8367RB"; + break; + case 0x1010: + chip_name = "8367R-VB"; + break; default: + REG_RD(smi, RTL8367B_CHIP_NUMBER_REG, &chip_num); + REG_RD(smi, RTL8367B_CHIP_MODE_REG, &chip_mode); + dev_err(smi->parent, "unknown chip num:%04x ver:%04x, mode:%04x\n", chip_num, chip_ver, chip_mode); @@ -1486,6 +1611,8 @@ static int rtl8367b_detect(struct rtl8366_smi *smi) dev_info(smi->parent, "RTL%s chip found\n", chip_name); + smi->chip_ver = chip_ver; + return 0; } @@ -1510,7 +1637,7 @@ static struct rtl8366_smi_ops rtl8367b_smi_ops = { .enable_port = rtl8367b_enable_port, }; -static int rtl8367b_probe(struct platform_device *pdev) +static int rtl8367b_probe(struct platform_device *pdev) { struct rtl8366_smi *smi; int err; @@ -1599,4 +1726,3 @@ MODULE_DESCRIPTION("Realtek RTL8367B ethernet switch driver"); MODULE_AUTHOR("Gabor Juhos "); MODULE_LICENSE("GPL v2"); MODULE_ALIAS("platform:" RTL8367B_DRIVER_NAME); - diff --git a/target/linux/ramips/dts/DIR-645.dts b/target/linux/ramips/dts/DIR-645.dts index 9c8082ca2443..64f0de53ff15 100644 --- a/target/linux/ramips/dts/DIR-645.dts +++ b/target/linux/ramips/dts/DIR-645.dts @@ -12,7 +12,7 @@ compatible = "realtek,rtl8367b"; gpio-sda = <&gpio0 1 0>; gpio-sck = <&gpio0 2 0>; - realtek,extif1 = <1 0 1 1 1 1 1 1 2>; + realtek,extif0 = <1 0 1 1 1 1 1 1 2>; }; gpio-keys-polled { diff --git a/target/linux/ramips/dts/kng_rc.dts b/target/linux/ramips/dts/kng_rc.dts index 7cd4de3fb254..baaee3fd59f6 100644 --- a/target/linux/ramips/dts/kng_rc.dts +++ b/target/linux/ramips/dts/kng_rc.dts @@ -75,8 +75,7 @@ rtl8367rb { compatible = "realtek,rtl8367b"; - cpu_port = <7>; - realtek,extif2 = <1 0 1 1 1 1 1 1 2>; + realtek,extif1 = <1 0 1 1 1 1 1 1 2>; mdio = <&mdio0>; }; };