diff options
Diffstat (limited to 'target')
-rw-r--r-- | target/linux/realtek/files-5.4/drivers/net/phy/rtl83xx-phy.c | 529 | ||||
-rw-r--r-- | target/linux/realtek/files-5.4/drivers/net/phy/rtl83xx-phy.h | 22 |
2 files changed, 523 insertions, 28 deletions
diff --git a/target/linux/realtek/files-5.4/drivers/net/phy/rtl83xx-phy.c b/target/linux/realtek/files-5.4/drivers/net/phy/rtl83xx-phy.c index eba416934f..78953c6d17 100644 --- a/target/linux/realtek/files-5.4/drivers/net/phy/rtl83xx-phy.c +++ b/target/linux/realtek/files-5.4/drivers/net/phy/rtl83xx-phy.c @@ -22,35 +22,50 @@ static const struct firmware rtl838x_8380_fw; static const struct firmware rtl838x_8214fc_fw; static const struct firmware rtl838x_8218b_fw; +int rtl930x_read_mmd_phy(u32 port, u32 devnum, u32 regnum, u32 *val); +int rtl930x_write_mmd_phy(u32 port, u32 addr, u32 reg, u32 val); static int read_phy(u32 port, u32 page, u32 reg, u32 *val) -{ - if (soc_info.family == RTL8390_FAMILY_ID) - return rtl839x_read_phy(port, page, reg, val); - else +{ switch (soc_info.family) { + case RTL8380_FAMILY_ID: return rtl838x_read_phy(port, page, reg, val); + case RTL8390_FAMILY_ID: + return rtl839x_read_phy(port, page, reg, val); + case RTL9300_FAMILY_ID: + return rtl930x_read_phy(port, page, reg, val); + case RTL9310_FAMILY_ID: + return rtl931x_read_phy(port, page, reg, val); + } + return -1; } static int write_phy(u32 port, u32 page, u32 reg, u32 val) { - if (soc_info.family == RTL8390_FAMILY_ID) - return rtl839x_write_phy(port, page, reg, val); - else + switch (soc_info.family) { + case RTL8380_FAMILY_ID: return rtl838x_write_phy(port, page, reg, val); + case RTL8390_FAMILY_ID: + return rtl839x_write_phy(port, page, reg, val); + case RTL9300_FAMILY_ID: + return rtl930x_write_phy(port, page, reg, val); + case RTL9310_FAMILY_ID: + return rtl931x_write_phy(port, page, reg, val); + } + return -1; } -static void int_phy_on_off(int mac, bool on) +static void rtl8380_int_phy_on_off(int mac, bool on) { u32 val; read_phy(mac, 0, 0, &val); if (on) - write_phy(mac, 0, 0, val & ~(1 << 11)); + write_phy(mac, 0, 0, val & ~BIT(11)); else - write_phy(mac, 0, 0, val | (1 << 11)); + write_phy(mac, 0, 0, val | BIT(11)); } -static void rtl8214fc_on_off(int mac, bool on) +static void rtl8380_rtl8214fc_on_off(int mac, bool on) { u32 val; @@ -58,25 +73,194 @@ static void rtl8214fc_on_off(int mac, bool on) write_phy(mac, 4095, 30, 3); read_phy(mac, 0, 16, &val); if (on) - write_phy(mac, 0, 16, val & ~(1 << 11)); + write_phy(mac, 0, 16, val & ~BIT(11)); else - write_phy(mac, 0, 16, val | (1 << 11)); + write_phy(mac, 0, 16, val | BIT(11)); /* copper ports */ write_phy(mac, 4095, 30, 1); read_phy(mac, 0, 16, &val); if (on) - write_phy(mac, 0xa40, 16, val & ~(1 << 11)); + write_phy(mac, 0xa40, 16, val & ~BIT(11)); else - write_phy(mac, 0xa40, 16, val | (1 << 11)); + write_phy(mac, 0xa40, 16, val | BIT(11)); } -static void phy_reset(int mac) +static void rtl8380_phy_reset(int mac) { u32 val; read_phy(mac, 0, 0, &val); - write_phy(mac, 0, 0, val | (0x1 << 15)); + write_phy(mac, 0, 0, val | BIT(15)); +} + +static void rtl8380_sds_rst(int mac) +{ + u32 offset = (mac == 24) ? 0 : 0x100; + + sw_w32_mask(1 << 11, 0, RTL8380_SDS4_FIB_REG0 + offset); + sw_w32_mask(0x3, 0, RTL838X_SDS4_REG28 + offset); + sw_w32_mask(0x3, 0x3, RTL838X_SDS4_REG28 + offset); + sw_w32_mask(0, 0x1 << 6, RTL838X_SDS4_DUMMY0 + offset); + sw_w32_mask(0x1 << 6, 0, RTL838X_SDS4_DUMMY0 + offset); + pr_info("SERDES reset: %d\n", mac); +} + +/* + * Reset the SerDes by powering it off and set a new operations mode + * of the SerDes. 0x1f is off. Other modes are + * 0x01: QSGMII 0x04: 1000BX_FIBER 0x05: FIBER100 + * 0x06: QSGMII 0x09: RSGMII 0x0d: USXGMII + * 0x10: XSGMII 0x12: HISGMII 0x16: 2500Base_X + * 0x17: RXAUI_LITE 0x19: RXAUI_PLUS 0x1a: 10G Base-R + * 0x1b: 10GR1000BX_AUTO 0x1f: OFF + */ +void rtl9300_sds_rst(int sds_num, u32 mode) +{ + // The access registers for SDS_MODE_SEL and the LSB for each SDS within + u16 regs[] = { 0x0194, 0x0194, 0x0194, 0x0194, 0x02a0, 0x02a0, 0x02a0, 0x02a0, + 0x02A4, 0x02A4, 0x0198, 0x0198 }; + u8 lsb[] = { 0, 6, 12, 18, 0, 6, 12, 18, 0, 6, 0, 6}; + + pr_info("SerDes: %s %d\n", __func__, mode); + if (sds_num < 0 || sds_num > 11) { + pr_err("Wrong SerDes number: %d\n", sds_num); + return; + } + + sw_w32_mask(0x1f << lsb[sds_num], 0x1f << lsb[sds_num], regs[sds_num]); + mdelay(10); + + sw_w32_mask(0x1f << lsb[sds_num], mode << lsb[sds_num], regs[sds_num]); + mdelay(10); + + pr_info("SDS: 194:%08x 198:%08x 2a0:%08x 2a4:%08x\n", + sw_r32(0x194), sw_r32(0x198), sw_r32(0x2a0), sw_r32(0x2a4)); +} + +/* + * On the RTL839x family of SoCs with inbuilt SerDes, these SerDes are accessed through + * a 2048 bit register that holds the contents of the PHY being simulated by the SoC. + */ +int rtl839x_read_sds_phy(int phy_addr, int phy_reg) +{ + int offset = 0; + int reg; + u32 val; + + if (phy_addr == 49) + offset = 0x100; + + /* + * For the RTL8393 internal SerDes, we simulate a PHY ID in registers 2/3 + * which would otherwise read as 0. + */ + if (soc_info.id == 0x8393) { + if (phy_reg == 2) + return 0x1c; + if (phy_reg == 3) + return 0x8393; + } + + /* + * Register RTL839X_SDS12_13_XSG0 is 2048 bit broad, the MSB (bit 15) of the + * 0th PHY register is bit 1023 (in byte 0x80). Because PHY-registers are 16 + * bit broad, we offset by reg << 1. In the SoC 2 registers are stored in + * one 32 bit register. + */ + reg = (phy_reg << 1) & 0xfc; + val = sw_r32(RTL839X_SDS12_13_XSG0 + offset + 0x80 + reg); + + if (phy_reg & 1) + val = (val >> 16) & 0xffff; + else + val &= 0xffff; + return val; +} + +/* + * On the RTL930x family of SoCs, the internal SerDes are accessed through an IO + * register which simulates commands to an internal MDIO bus. + */ +int rtl930x_read_sds_phy(int phy_addr, int page, int phy_reg) +{ + int i; + u32 cmd = phy_addr << 2 | page << 7 | phy_reg << 13 | 1; + + pr_info("%s: phy_addr %d, phy_reg: %d\n", __func__, phy_addr, phy_reg); + sw_w32(cmd, RTL930X_SDS_INDACS_CMD); + + for (i = 0; i < 100; i++) { + if (!(sw_r32(RTL930X_SDS_INDACS_CMD) & 0x1)) + break; + mdelay(1); + } + + if (i >= 100) + return -EIO; + + pr_info("%s: returning %04x\n", __func__, sw_r32(RTL930X_SDS_INDACS_DATA) & 0xffff); + return sw_r32(RTL930X_SDS_INDACS_DATA) & 0xffff; +} + +int rtl930x_write_sds_phy(int phy_addr, int page, int phy_reg, u16 v) +{ + int i; + u32 cmd; + + sw_w32(v, RTL930X_SDS_INDACS_DATA); + cmd = phy_addr << 2 | page << 7 | phy_reg << 13 | 0x3; + + for (i = 0; i < 100; i++) { + if (!(sw_r32(RTL930X_SDS_INDACS_CMD) & 0x1)) + break; + mdelay(1); + } + + if (i >= 100) + return -EIO; + + return 0; +} + +/* + * On the RTL838x SoCs, the internal SerDes is accessed through direct access to + * standard PHY registers, where a 32 bit register holds a 16 bit word as found + * in a standard page 0 of a PHY + */ +int rtl838x_read_sds_phy(int phy_addr, int phy_reg) +{ + int offset = 0; + u32 val; + + if (phy_addr == 26) + offset = 0x100; + val = sw_r32(RTL838X_SDS4_FIB_REG0 + offset + (phy_reg << 2)) & 0xffff; + + return val; +} + +int rtl839x_write_sds_phy(int phy_addr, int phy_reg, u16 v) +{ + int offset = 0; + int reg; + u32 val; + + if (phy_addr == 49) + offset = 0x100; + + reg = (phy_reg << 1) & 0xfc; + val = v; + if (phy_reg & 1) { + val = val << 16; + sw_w32_mask(0xffff0000, val, + RTL839X_SDS12_13_XSG0 + offset + 0x80 + reg); + } else { + sw_w32_mask(0xffff, val, + RTL839X_SDS12_13_XSG0 + offset + 0x80 + reg); + } + + return 0; } /* Read the link and speed status of the 2 internal SGMII/1000Base-X @@ -123,6 +307,149 @@ static int rtl8393_read_status(struct phy_device *phydev) return err; } +static int rtl8226_read_page(struct phy_device *phydev) +{ + return __phy_read(phydev, 0x1f); +} + +static int rtl8226_write_page(struct phy_device *phydev, int page) +{ + return __phy_write(phydev, 0x1f, page); +} + +static int rtl8226_read_status(struct phy_device *phydev) +{ + int ret = 0, i; + u32 val; + int port = phydev->mdio.addr; + +// TODO: ret = genphy_read_status(phydev); +// if (ret < 0) { +// pr_info("%s: genphy_read_status failed\n", __func__); +// return ret; +// } + + // Link status must be read twice + for (i = 0; i < 2; i++) { + rtl930x_read_mmd_phy(port, MMD_VEND2, 0xA402, &val); + } + phydev->link = val & BIT(2) ? 1 : 0; + if (!phydev->link) + goto out; + + // Read duplex status + ret = rtl930x_read_mmd_phy(port, MMD_VEND2, 0xA434, &val); + if (ret) + goto out; + phydev->duplex = !!(val & BIT(3)); + + // Read speed + ret = rtl930x_read_mmd_phy(port, MMD_VEND2, 0xA434, &val); + switch (val & 0x0630) { + case 0x0000: + phydev->speed = SPEED_10; + break; + case 0x0010: + phydev->speed = SPEED_100; + break; + case 0x0020: + phydev->speed = SPEED_1000; + break; + case 0x0200: + phydev->speed = SPEED_10000; + break; + case 0x0210: + phydev->speed = SPEED_2500; + break; + case 0x0220: + phydev->speed = SPEED_5000; + break; + default: + break; + } +out: + return ret; +} + +static int rtl8266_advertise_aneg(struct phy_device *phydev) +{ + int ret = 0; + u32 v; + int port = phydev->mdio.addr; + + pr_info("In %s\n", __func__); + + ret = rtl930x_read_mmd_phy(port, MMD_AN, 16, &v); + if (ret) + goto out; + + v |= BIT(5); // HD 10M + v |= BIT(6); // FD 10M + v |= BIT(7); // HD 100M + v |= BIT(8); // FD 100M + + ret = rtl930x_write_mmd_phy(port, MMD_AN, 16, v); + + // Allow 1GBit + ret = rtl930x_read_mmd_phy(port, MMD_VEND2, 0xA412, &v); + if (ret) + goto out; + v |= BIT(9); // FD 1000M + + ret = rtl930x_write_mmd_phy(port, MMD_VEND2, 0xA412, v); + if (ret) + goto out; + + // Allow 2.5G + ret = rtl930x_read_mmd_phy(port, MMD_AN, 32, &v); + if (ret) + goto out; + + v |= BIT(7); + ret = rtl930x_write_mmd_phy(port, MMD_AN, 32, v); + +out: + return ret; +} + + +static int rtl8226_config_aneg(struct phy_device *phydev) +{ + int ret = 0; + u32 v; + int port = phydev->mdio.addr; + + pr_info("In %s\n", __func__); + if (phydev->autoneg == AUTONEG_ENABLE) { + ret = rtl8266_advertise_aneg(phydev); + if (ret) + goto out; + // AutoNegotiationEnable + ret = rtl930x_read_mmd_phy(port, MMD_AN, 0, &v); + if (ret) + goto out; + + v |= BIT(12); // Enable AN + ret = rtl930x_write_mmd_phy(port, MMD_AN, 0, v); + if (ret) + goto out; + + // RestartAutoNegotiation + ret = rtl930x_read_mmd_phy(port, MMD_VEND2, 0xA400, &v); + if (ret) + goto out; + v |= BIT(9); + + ret = rtl930x_write_mmd_phy(port, MMD_VEND2, 0xA400, v); + } + + pr_info("%s: Ret is already: %d\n", __func__, ret); +// TODO: ret = __genphy_config_aneg(phydev, ret); + +out: + pr_info("%s: And ret is now: %d\n", __func__, ret); + return ret; +} static struct fw_header *rtl838x_request_fw(struct phy_device *phydev, const struct firmware *fw, @@ -234,9 +561,9 @@ static int rtl8380_configure_int_rtl8218b(struct phy_device *phydev) read_phy(mac, 0, 0, &val); if (val & (1 << 11)) - int_phy_on_off(mac, true); + rtl8380_int_phy_on_off(mac, true); else - phy_reset(mac); + rtl8380_phy_reset(mac); msleep(100); /* Ready PHY for patch */ @@ -326,9 +653,9 @@ static int rtl8380_configure_ext_rtl8218b(struct phy_device *phydev) read_phy(mac, 0, 0, &val); if (val & (1 << 11)) - int_phy_on_off(mac, true); + rtl8380_int_phy_on_off(mac, true); else - phy_reset(mac); + rtl8380_phy_reset(mac); msleep(100); /* Get Chip revision */ @@ -517,6 +844,26 @@ static int rtl8218b_write_mmd(struct phy_device *phydev, return rtl838x_write_mmd_phy(addr, devnum, regnum, val); } +static int rtl8226_read_mmd(struct phy_device *phydev, int devnum, u16 regnum) +{ + int port = phydev->mdio.addr; // the SoC translates port addresses to PHY addr + int err; + u32 val; + + err = rtl930x_read_mmd_phy(port, devnum, regnum, &val); + + if (err) + return err; + return val; +} + +static int rtl8226_write_mmd(struct phy_device *phydev, int devnum, u16 regnum, u16 val) +{ + int port = phydev->mdio.addr; // the SoC translates port addresses to PHY addr + + return rtl930x_write_mmd_phy(port, devnum, regnum, val); +} + static void rtl8380_rtl8214fc_media_set(int mac, bool set_fibre) { int base = mac - (mac % 4); @@ -654,7 +1001,7 @@ static void rtl8218b_eee_set_u_boot(int port, bool enable) } // TODO: unused -static void rtl8380_rtl8218b_eee_set(int port, bool enable) +void rtl8380_rtl8218b_eee_set(int port, bool enable) { u32 val; bool an_enabled; @@ -720,7 +1067,7 @@ static int rtl8218b_get_eee(struct phy_device *phydev, } // TODO: unused -static void rtl8380_rtl8218b_green_set(int mac, bool enable) +void rtl8380_rtl8218b_green_set(int mac, bool enable) { u32 val; @@ -744,7 +1091,7 @@ static void rtl8380_rtl8218b_green_set(int mac, bool enable) } // TODO: unused -static int rtl8380_rtl8214fc_get_green(struct phy_device *phydev, struct ethtool_eee *e) +int rtl8380_rtl8214fc_get_green(struct phy_device *phydev, struct ethtool_eee *e) { u32 val; int addr = phydev->mdio.addr; @@ -886,9 +1233,9 @@ static int rtl8380_configure_rtl8214fc(struct phy_device *phydev) read_phy(mac, 0, 16, &val); if (val & (1 << 11)) - rtl8214fc_on_off(mac, true); + rtl8380_rtl8214fc_on_off(mac, true); else - phy_reset(mac); + rtl8380_phy_reset(mac); msleep(100); write_phy(mac, 0, 30, 0x0001); @@ -1143,6 +1490,45 @@ static int rtl8390_configure_serdes(struct phy_device *phydev) return 0; } +int rtl9300_configure_serdes(struct phy_device *phydev) +{ + struct device *dev = &phydev->mdio.dev; + int phy_addr = phydev->mdio.addr; + int sds_num = 0; + int v; + + phydev_info(phydev, "Configuring internal RTL9300 SERDES\n"); + + switch (phy_addr) { + case 26: + sds_num = 8; + break; + case 27: + sds_num = 9; + break; + default: + dev_err(dev, "Not a SerDes PHY\n"); + return -EINVAL; + } + + /* Set default Medium to fibre */ + v = rtl930x_read_sds_phy(sds_num, 0x1f, 11); + if (v < 0) { + dev_err(dev, "Cannot access SerDes PHY %d\n", phy_addr); + return -EINVAL; + } + v |= BIT(2); + rtl930x_write_sds_phy(sds_num, 0x1f, 11, v); + + // TODO: this needs to be configurable via ethtool/.dts + pr_info("Setting 10G/1000BX auto fibre medium\n"); + rtl9300_sds_rst(sds_num, 0x1b); + + // TODO: Apply patch set for fibre type + + return 0; +} + static int rtl8214fc_phy_probe(struct phy_device *phydev) { struct device *dev = &phydev->mdio.dev; @@ -1232,6 +1618,43 @@ static int rtl8218b_int_phy_probe(struct phy_device *phydev) return 0; } +static int rtl8218d_phy_probe(struct phy_device *phydev) +{ + struct device *dev = &phydev->mdio.dev; + struct rtl838x_phy_priv *priv; + int addr = phydev->mdio.addr; + + pr_info("%s: id: %d\n", __func__, addr); + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + priv->name = "RTL8218D"; + + /* All base addresses of the PHYs start at multiples of 8 */ + if (!(addr % 8)) { + /* Configuration must be done while patching still possible */ +// TODO: return configure_rtl8218d(phydev); + } + return 0; +} + +static int rtl8226_phy_probe(struct phy_device *phydev) +{ + struct device *dev = &phydev->mdio.dev; + struct rtl838x_phy_priv *priv; + int addr = phydev->mdio.addr; + + pr_info("%s: id: %d\n", __func__, addr); + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + priv->name = "RTL8226"; + + return 0; +} + static int rtl838x_serdes_probe(struct phy_device *phydev) { struct device *dev = &phydev->mdio.dev; @@ -1299,6 +1722,26 @@ static int rtl8390_serdes_probe(struct phy_device *phydev) return rtl8390_configure_generic(phydev); } +static int rtl9300_serdes_probe(struct phy_device *phydev) +{ + struct device *dev = &phydev->mdio.dev; + struct rtl838x_phy_priv *priv; + int addr = phydev->mdio.addr; + + if (soc_info.family != RTL9300_FAMILY_ID) + return -ENODEV; + + if (addr < 24) + return -ENODEV; + + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + priv->name = "RTL9300 Serdes"; + return rtl9300_configure_serdes(phydev); +} + static struct phy_driver rtl83xx_phy_driver[] = { { PHY_ID_MATCH_MODEL(PHY_ID_RTL8214C), @@ -1341,6 +1784,29 @@ static struct phy_driver rtl83xx_phy_driver[] = { .get_eee = rtl8218b_get_eee, }, { + PHY_ID_MATCH_MODEL(PHY_ID_RTL8218D), + .name = "REALTEK RTL8218D", + .features = PHY_GBIT_FEATURES, + .probe = rtl8218d_phy_probe, + .suspend = genphy_suspend, + .resume = genphy_resume, + .set_loopback = genphy_loopback, + }, { + PHY_ID_MATCH_MODEL(PHY_ID_RTL8226), + .name = "REALTEK RTL8226", + .features = PHY_GBIT_FEATURES, + .probe = rtl8226_phy_probe, + .suspend = genphy_suspend, + .resume = genphy_resume, + .set_loopback = genphy_loopback, + .read_mmd = rtl8226_read_mmd, + .write_mmd = rtl8226_write_mmd, + .read_page = rtl8226_read_page, + .write_page = rtl8226_write_page, + .read_status = rtl8226_read_status, + .config_aneg = rtl8226_config_aneg, + }, + { PHY_ID_MATCH_MODEL(PHY_ID_RTL8218B_I), .name = "Realtek RTL8218B (internal)", .features = PHY_GBIT_FEATURES, @@ -1383,7 +1849,16 @@ static struct phy_driver rtl83xx_phy_driver[] = { .suspend = genphy_suspend, .resume = genphy_resume, .set_loopback = genphy_loopback, - } + }, + { + PHY_ID_MATCH_MODEL(PHY_ID_RTL9300_I), + .name = "REALTEK RTL9300 SERDES", + .features = PHY_GBIT_FIBRE_FEATURES, + .probe = rtl9300_serdes_probe, + .suspend = genphy_suspend, + .resume = genphy_resume, + .set_loopback = genphy_loopback, + }, }; module_phy_driver(rtl83xx_phy_driver); diff --git a/target/linux/realtek/files-5.4/drivers/net/phy/rtl83xx-phy.h b/target/linux/realtek/files-5.4/drivers/net/phy/rtl83xx-phy.h index 7af35a3583..031ec8a0e9 100644 --- a/target/linux/realtek/files-5.4/drivers/net/phy/rtl83xx-phy.h +++ b/target/linux/realtek/files-5.4/drivers/net/phy/rtl83xx-phy.h @@ -28,13 +28,33 @@ struct __attribute__ ((__packed__)) fw_header { #define PHY_ID_RTL8214C 0x001cc942 #define PHY_ID_RTL8214FC 0x001cc981 #define PHY_ID_RTL8218B_E 0x001cc981 +#define PHY_ID_RTL8218D 0x001cc983 #define PHY_ID_RTL8218B_I 0x001cca40 +#define PHY_ID_RTL8226 0x001cc838 #define PHY_ID_RTL8390_GENERIC 0x001ccab0 #define PHY_ID_RTL8393_I 0x001c8393 +#define PHY_ID_RTL9300_I 0x70d03106 -#define RTL839X_SDS12_13_XSG0 (0xB800) +// PHY MMD devices +#define MMD_AN 7 +#define MMD_VEND2 31 +/* Registers of the internal Serdes of the 8380 */ #define RTL838X_SDS_MODE_SEL (0x0028) #define RTL838X_SDS_CFG_REG (0x0034) #define RTL838X_INT_MODE_CTRL (0x005c) #define RTL838X_DMY_REG31 (0x3b28) + +#define RTL8380_SDS4_FIB_REG0 (0xF800) +#define RTL838X_SDS4_REG28 (0xef80) +#define RTL838X_SDS4_DUMMY0 (0xef8c) +#define RTL838X_SDS5_EXT_REG6 (0xf18c) +#define RTL838X_SDS4_FIB_REG0 (RTL838X_SDS4_REG28 + 0x880) +#define RTL838X_SDS5_FIB_REG0 (RTL838X_SDS4_REG28 + 0x980) + +/* Registers of the internal SerDes of the RTL8390 */ +#define RTL839X_SDS12_13_XSG0 (0xB800) + +/* Registers of the internal Serdes of the 9300 */ +#define RTL930X_SDS_INDACS_CMD (0x03B0) +#define RTL930X_SDS_INDACS_DATA (0x03B4) |