Add support for the SRAM access interface of the RTL8157 and the ADV indirect access interface. Signed-off-by: Birger Koblitz --- drivers/net/usb/r8152.c | 161 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 161 insertions(+) diff --git a/drivers/net/usb/r8152.c b/drivers/net/usb/r8152.c index cefc08fd15c824025ae10426dcf41609687a723e..45b79a0138f0440a8cb0b2124b2b71b85a319b6b 100644 --- a/drivers/net/usb/r8152.c +++ b/drivers/net/usb/r8152.c @@ -156,6 +156,9 @@ #define USB_U1U2_TIMER 0xd4da #define USB_FW_TASK 0xd4e8 /* RTL8153B */ #define USB_RX_AGGR_NUM 0xd4ee +#define USB_ADV_ADDR 0xd5d6 +#define USB_ADV_DATA 0xd5d8 +#define USB_ADV_CMD 0xd5dc #define USB_UPS_CTRL 0xd800 #define USB_POWER_CUT 0xd80a #define USB_MISC_0 0xd81a @@ -213,6 +216,8 @@ #define OCP_PHY_PATCH_STAT 0xb800 #define OCP_PHY_PATCH_CMD 0xb820 #define OCP_PHY_LOCK 0xb82e +#define OCP_SRAM2_ADDR 0xb87c +#define OCP_SRAM2_DATA 0xb87e #define OCP_ADC_IOFFSET 0xbcfc #define OCP_ADC_CFG 0xbc06 #define OCP_SYSCLK_CFG 0xc416 @@ -490,6 +495,12 @@ /* USB_RX_AGGR_NUM */ #define RX_AGGR_NUM_MASK 0x1ff +/* USB_ADV_CMD */ +#define ADV_CMD_BMU 0 +#define ADV_CMD_BUSY BIT(0) +#define ADV_CMD_WR BIT(1) +#define ADV_CMD_IP BIT(2) + /* USB_UPS_CTRL */ #define POWER_CUT 0x0100 @@ -1656,6 +1667,134 @@ static inline int r8152_mdio_read(struct r8152 *tp, u32 reg_addr) return ocp_reg_read(tp, OCP_BASE_MII + reg_addr * 2); } +static int wait_cmd_ready(struct r8152 *tp, u16 cmd) +{ + int i, ret; + + for (i = 0; i < 10; i++) { + u16 ocp_data = ocp_read_word(tp, MCU_TYPE_USB, cmd); + + if (!(ocp_data & ADV_CMD_BUSY)) + break; + usleep_range(1000, 2000); + } + + if (i == 10) + ret = -ETIMEDOUT; + + return ret; +} + +static u32 ocp_adv_read(struct r8152 *tp, u16 cmd, u16 addr, u32 *data) +{ + int ret; + + ret = wait_cmd_ready(tp, USB_ADV_CMD); + if (ret < 0) + goto out; + + ocp_write_word(tp, MCU_TYPE_USB, USB_ADV_ADDR, addr); + + cmd |= ADV_CMD_BUSY; + ocp_write_word(tp, MCU_TYPE_USB, USB_ADV_CMD, cmd); + + ret = wait_cmd_ready(tp, USB_ADV_CMD); + if (ret < 0) + goto out; + + *data = ocp_read_dword(tp, MCU_TYPE_USB, USB_ADV_DATA); + +out: + return ret; +} + +static int ocp_adv_write(struct r8152 *tp, u16 cmd, u16 addr, u32 data) +{ + int ret; + + ret = wait_cmd_ready(tp, USB_ADV_CMD); + if (ret < 0) + goto out; + + cmd |= ADV_CMD_WR; + ocp_write_dword(tp, MCU_TYPE_USB, USB_ADV_DATA, data); + + ocp_write_word(tp, MCU_TYPE_USB, USB_ADV_ADDR, addr); + + cmd |= ADV_CMD_BUSY; + ocp_write_word(tp, MCU_TYPE_USB, USB_ADV_CMD, cmd); + +out: + return ret; +} + +static int rtl_bmu_read(struct r8152 *tp, u16 addr, u32 *data) +{ + return ocp_adv_read(tp, ADV_CMD_BMU, addr, data); +} + +static int rtl_bmu_write(struct r8152 *tp, u16 addr, u32 data) +{ + return ocp_adv_write(tp, ADV_CMD_BMU, addr, data); +} + +static int rtl_bmu_w0w1(struct r8152 *tp, u16 addr, u32 clear, u32 set) +{ + u32 bmu; + int ret; + + ret = rtl_bmu_read(tp, addr, &bmu); + if (ret < 0) + goto out; + + bmu = (bmu & ~clear) | set; + ret = rtl_bmu_write(tp, addr, bmu); + +out: + return ret; +} + +static int rtl_bmu_clr_bits(struct r8152 *tp, u16 addr, u32 clear) +{ + return rtl_bmu_w0w1(tp, addr, clear, 0); +} + +static int rtl_ip_read(struct r8152 *tp, u16 addr, u32 *data) +{ + return ocp_adv_read(tp, ADV_CMD_IP, addr, data); +} + +static int rtl_ip_write(struct r8152 *tp, u16 addr, u32 data) +{ + return ocp_adv_write(tp, ADV_CMD_IP, addr, data); +} + +static int rtl_ip_w0w1(struct r8152 *tp, u16 addr, u32 clear, u32 set) +{ + int ret; + u32 ip; + + ret = rtl_ip_read(tp, addr, &ip); + if (ret < 0) + goto out; + + ip = (ip & ~clear) | set; + ret = rtl_ip_write(tp, addr, ip); + +out: + return ret; +} + +static int rtl_ip_clr_bits(struct r8152 *tp, u16 addr, u32 clear) +{ + return rtl_ip_w0w1(tp, addr, clear, 0); +} + +static int rtl_ip_set_bits(struct r8152 *tp, u16 addr, u32 set) +{ + return rtl_ip_w0w1(tp, addr, 0, set); +} + static void sram_write(struct r8152 *tp, u16 addr, u16 data) { ocp_reg_write(tp, OCP_SRAM_ADDR, addr); @@ -1668,6 +1807,28 @@ static u16 sram_read(struct r8152 *tp, u16 addr) return ocp_reg_read(tp, OCP_SRAM_DATA); } +static void sram_write_w0w1(struct r8152 *tp, u16 addr, u16 clear, u16 set) +{ + u16 data = sram_read(tp, addr); + + data = (data & ~clear) | set; + ocp_reg_write(tp, OCP_SRAM_DATA, data); +} + +static u16 sram2_read(struct r8152 *tp, u16 addr) +{ + ocp_reg_write(tp, OCP_SRAM2_ADDR, addr); + return ocp_reg_read(tp, OCP_SRAM2_DATA); +} + +static void sram2_write_w0w1(struct r8152 *tp, u16 addr, u16 clear, u16 set) +{ + u16 data = sram2_read(tp, addr); + + data = (data & ~clear) | set; + ocp_reg_write(tp, OCP_SRAM2_DATA, data); +} + static int read_mii_word(struct net_device *netdev, int phy_id, int reg) { struct r8152 *tp = netdev_priv(netdev); -- 2.47.3