1/* 2 * Platform driver for the Realtek RTL8367R/M ethernet switches 3 * 4 * Copyright (C) 2011 Gabor Juhos <juhosg@openwrt.org> 5 * 6 * This program is free software; you can redistribute it and/or modify it 7 * under the terms of the GNU General Public License version 2 as published 8 * by the Free Software Foundation. 9 */ 10 11#include <linux/kernel.h> 12#include <linux/module.h> 13#include <linux/init.h> 14#include <linux/device.h> 15#include <linux/of.h> 16#include <linux/of_platform.h> 17#include <linux/delay.h> 18#include <linux/skbuff.h> 19#include <linux/rtl8367.h> 20 21#include "rtl8366_smi.h" 22 23#define RTL8367_RESET_DELAY 1000 /* msecs*/ 24 25#define RTL8367_PHY_ADDR_MAX 8 26#define RTL8367_PHY_REG_MAX 31 27 28#define RTL8367_VID_MASK 0xffff 29#define RTL8367_FID_MASK 0xfff 30#define RTL8367_UNTAG_MASK 0xffff 31#define RTL8367_MEMBER_MASK 0xffff 32 33#define RTL8367_PORT_CFG_REG(_p) (0x000e + 0x20 * (_p)) 34#define RTL8367_PORT_CFG_EGRESS_MODE_SHIFT 4 35#define RTL8367_PORT_CFG_EGRESS_MODE_MASK 0x3 36#define RTL8367_PORT_CFG_EGRESS_MODE_ORIGINAL 0 37#define RTL8367_PORT_CFG_EGRESS_MODE_KEEP 1 38#define RTL8367_PORT_CFG_EGRESS_MODE_PRI 2 39#define RTL8367_PORT_CFG_EGRESS_MODE_REAL 3 40 41#define RTL8367_BYPASS_LINE_RATE_REG 0x03f7 42 43#define RTL8367_TA_CTRL_REG 0x0500 44#define RTL8367_TA_CTRL_STATUS BIT(12) 45#define RTL8367_TA_CTRL_METHOD BIT(5) 46#define RTL8367_TA_CTRL_CMD_SHIFT 4 47#define RTL8367_TA_CTRL_CMD_READ 0 48#define RTL8367_TA_CTRL_CMD_WRITE 1 49#define RTL8367_TA_CTRL_TABLE_SHIFT 0 50#define RTL8367_TA_CTRL_TABLE_ACLRULE 1 51#define RTL8367_TA_CTRL_TABLE_ACLACT 2 52#define RTL8367_TA_CTRL_TABLE_CVLAN 3 53#define RTL8367_TA_CTRL_TABLE_L2 4 54#define RTL8367_TA_CTRL_CVLAN_READ \ 55 ((RTL8367_TA_CTRL_CMD_READ << RTL8367_TA_CTRL_CMD_SHIFT) | \ 56 RTL8367_TA_CTRL_TABLE_CVLAN) 57#define RTL8367_TA_CTRL_CVLAN_WRITE \ 58 ((RTL8367_TA_CTRL_CMD_WRITE << RTL8367_TA_CTRL_CMD_SHIFT) | \ 59 RTL8367_TA_CTRL_TABLE_CVLAN) 60 61#define RTL8367_TA_ADDR_REG 0x0501 62#define RTL8367_TA_ADDR_MASK 0x3fff 63 64#define RTL8367_TA_DATA_REG(_x) (0x0503 + (_x)) 65#define RTL8367_TA_VLAN_DATA_SIZE 4 66#define RTL8367_TA_VLAN_VID_MASK RTL8367_VID_MASK 67#define RTL8367_TA_VLAN_MEMBER_SHIFT 0 68#define RTL8367_TA_VLAN_MEMBER_MASK RTL8367_MEMBER_MASK 69#define RTL8367_TA_VLAN_FID_SHIFT 0 70#define RTL8367_TA_VLAN_FID_MASK RTL8367_FID_MASK 71#define RTL8367_TA_VLAN_UNTAG1_SHIFT 14 72#define RTL8367_TA_VLAN_UNTAG1_MASK 0x3 73#define RTL8367_TA_VLAN_UNTAG2_SHIFT 0 74#define RTL8367_TA_VLAN_UNTAG2_MASK 0x3fff 75 76#define RTL8367_VLAN_PVID_CTRL_REG(_p) (0x0700 + (_p) / 2) 77#define RTL8367_VLAN_PVID_CTRL_MASK 0x1f 78#define RTL8367_VLAN_PVID_CTRL_SHIFT(_p) (8 * ((_p) % 2)) 79 80#define RTL8367_VLAN_MC_BASE(_x) (0x0728 + (_x) * 4) 81#define RTL8367_VLAN_MC_DATA_SIZE 4 82#define RTL8367_VLAN_MC_MEMBER_SHIFT 0 83#define RTL8367_VLAN_MC_MEMBER_MASK RTL8367_MEMBER_MASK 84#define RTL8367_VLAN_MC_FID_SHIFT 0 85#define RTL8367_VLAN_MC_FID_MASK RTL8367_FID_MASK 86#define RTL8367_VLAN_MC_EVID_SHIFT 0 87#define RTL8367_VLAN_MC_EVID_MASK RTL8367_VID_MASK 88 89#define RTL8367_VLAN_CTRL_REG 0x07a8 90#define RTL8367_VLAN_CTRL_ENABLE BIT(0) 91 92#define RTL8367_VLAN_INGRESS_REG 0x07a9 93 94#define RTL8367_PORT_ISOLATION_REG(_p) (0x08a2 + (_p)) 95 96#define RTL8367_MIB_COUNTER_REG(_x) (0x1000 + (_x)) 97 98#define RTL8367_MIB_ADDRESS_REG 0x1004 99 100#define RTL8367_MIB_CTRL_REG(_x) (0x1005 + (_x)) 101#define RTL8367_MIB_CTRL_GLOBAL_RESET_MASK BIT(11) 102#define RTL8367_MIB_CTRL_QM_RESET_MASK BIT(10) 103#define RTL8367_MIB_CTRL_PORT_RESET_MASK(_p) BIT(2 + (_p)) 104#define RTL8367_MIB_CTRL_RESET_MASK BIT(1) 105#define RTL8367_MIB_CTRL_BUSY_MASK BIT(0) 106 107#define RTL8367_MIB_COUNT 36 108#define RTL8367_MIB_COUNTER_PORT_OFFSET 0x0050 109 110#define RTL8367_SWC0_REG 0x1200 111#define RTL8367_SWC0_MAX_LENGTH_SHIFT 13 112#define RTL8367_SWC0_MAX_LENGTH(_x) ((_x) << 13) 113#define RTL8367_SWC0_MAX_LENGTH_MASK RTL8367_SWC0_MAX_LENGTH(0x3) 114#define RTL8367_SWC0_MAX_LENGTH_1522 RTL8367_SWC0_MAX_LENGTH(0) 115#define RTL8367_SWC0_MAX_LENGTH_1536 RTL8367_SWC0_MAX_LENGTH(1) 116#define RTL8367_SWC0_MAX_LENGTH_1552 RTL8367_SWC0_MAX_LENGTH(2) 117#define RTL8367_SWC0_MAX_LENGTH_16000 RTL8367_SWC0_MAX_LENGTH(3) 118 119#define RTL8367_CHIP_NUMBER_REG 0x1300 120 121#define RTL8367_CHIP_VER_REG 0x1301 122#define RTL8367_CHIP_VER_RLVID_SHIFT 12 123#define RTL8367_CHIP_VER_RLVID_MASK 0xf 124#define RTL8367_CHIP_VER_MCID_SHIFT 8 125#define RTL8367_CHIP_VER_MCID_MASK 0xf 126#define RTL8367_CHIP_VER_BOID_SHIFT 4 127#define RTL8367_CHIP_VER_BOID_MASK 0xf 128 129#define RTL8367_CHIP_MODE_REG 0x1302 130#define RTL8367_CHIP_MODE_MASK 0x7 131 132#define RTL8367_CHIP_DEBUG0_REG 0x1303 133#define RTL8367_CHIP_DEBUG0_DUMMY0(_x) BIT(8 + (_x)) 134 135#define RTL8367_CHIP_DEBUG1_REG 0x1304 136 137#define RTL8367_DIS_REG 0x1305 138#define RTL8367_DIS_SKIP_MII_RXER(_x) BIT(12 + (_x)) 139#define RTL8367_DIS_RGMII_SHIFT(_x) (4 * (_x)) 140#define RTL8367_DIS_RGMII_MASK 0x7 141 142#define RTL8367_EXT_RGMXF_REG(_x) (0x1306 + (_x)) 143#define RTL8367_EXT_RGMXF_DUMMY0_SHIFT 5 144#define RTL8367_EXT_RGMXF_DUMMY0_MASK 0x7ff 145#define RTL8367_EXT_RGMXF_TXDELAY_SHIFT 3 146#define RTL8367_EXT_RGMXF_TXDELAY_MASK 1 147#define RTL8367_EXT_RGMXF_RXDELAY_MASK 0x7 148 149#define RTL8367_DI_FORCE_REG(_x) (0x1310 + (_x)) 150#define RTL8367_DI_FORCE_MODE BIT(12) 151#define RTL8367_DI_FORCE_NWAY BIT(7) 152#define RTL8367_DI_FORCE_TXPAUSE BIT(6) 153#define RTL8367_DI_FORCE_RXPAUSE BIT(5) 154#define RTL8367_DI_FORCE_LINK BIT(4) 155#define RTL8367_DI_FORCE_DUPLEX BIT(2) 156#define RTL8367_DI_FORCE_SPEED_MASK 3 157#define RTL8367_DI_FORCE_SPEED_10 0 158#define RTL8367_DI_FORCE_SPEED_100 1 159#define RTL8367_DI_FORCE_SPEED_1000 2 160 161#define RTL8367_MAC_FORCE_REG(_x) (0x1312 + (_x)) 162 163#define RTL8367_CHIP_RESET_REG 0x1322 164#define RTL8367_CHIP_RESET_SW BIT(1) 165#define RTL8367_CHIP_RESET_HW BIT(0) 166 167#define RTL8367_PORT_STATUS_REG(_p) (0x1352 + (_p)) 168#define RTL8367_PORT_STATUS_NWAY BIT(7) 169#define RTL8367_PORT_STATUS_TXPAUSE BIT(6) 170#define RTL8367_PORT_STATUS_RXPAUSE BIT(5) 171#define RTL8367_PORT_STATUS_LINK BIT(4) 172#define RTL8367_PORT_STATUS_DUPLEX BIT(2) 173#define RTL8367_PORT_STATUS_SPEED_MASK 0x0003 174#define RTL8367_PORT_STATUS_SPEED_10 0 175#define RTL8367_PORT_STATUS_SPEED_100 1 176#define RTL8367_PORT_STATUS_SPEED_1000 2 177 178#define RTL8367_RTL_NO_REG 0x13c0 179#define RTL8367_RTL_NO_8367R 0x3670 180#define RTL8367_RTL_NO_8367M 0x3671 181 182#define RTL8367_RTL_VER_REG 0x13c1 183#define RTL8367_RTL_VER_MASK 0xf 184 185#define RTL8367_RTL_MAGIC_ID_REG 0x13c2 186#define RTL8367_RTL_MAGIC_ID_VAL 0x0249 187 188#define RTL8367_LED_SYS_CONFIG_REG 0x1b00 189#define RTL8367_LED_MODE_REG 0x1b02 190#define RTL8367_LED_MODE_RATE_M 0x7 191#define RTL8367_LED_MODE_RATE_S 1 192 193#define RTL8367_LED_CONFIG_REG 0x1b03 194#define RTL8367_LED_CONFIG_DATA_S 12 195#define RTL8367_LED_CONFIG_DATA_M 0x3 196#define RTL8367_LED_CONFIG_SEL BIT(14) 197#define RTL8367_LED_CONFIG_LED_CFG_M 0xf 198 199#define RTL8367_PARA_LED_IO_EN1_REG 0x1b24 200#define RTL8367_PARA_LED_IO_EN2_REG 0x1b25 201#define RTL8367_PARA_LED_IO_EN_PMASK 0xff 202 203#define RTL8367_IA_CTRL_REG 0x1f00 204#define RTL8367_IA_CTRL_RW(_x) ((_x) << 1) 205#define RTL8367_IA_CTRL_RW_READ RTL8367_IA_CTRL_RW(0) 206#define RTL8367_IA_CTRL_RW_WRITE RTL8367_IA_CTRL_RW(1) 207#define RTL8367_IA_CTRL_CMD_MASK BIT(0) 208 209#define RTL8367_IA_STATUS_REG 0x1f01 210#define RTL8367_IA_STATUS_PHY_BUSY BIT(2) 211#define RTL8367_IA_STATUS_SDS_BUSY BIT(1) 212#define RTL8367_IA_STATUS_MDX_BUSY BIT(0) 213 214#define RTL8367_IA_ADDRESS_REG 0x1f02 215 216#define RTL8367_IA_WRITE_DATA_REG 0x1f03 217#define RTL8367_IA_READ_DATA_REG 0x1f04 218 219#define RTL8367_INTERNAL_PHY_REG(_a, _r) (0x2000 + 32 * (_a) + (_r)) 220 221#define RTL8367_CPU_PORT_NUM 9 222#define RTL8367_NUM_PORTS 10 223#define RTL8367_NUM_VLANS 32 224#define RTL8367_NUM_LEDGROUPS 4 225#define RTL8367_NUM_VIDS 4096 226#define RTL8367_PRIORITYMAX 7 227#define RTL8367_FIDMAX 7 228 229#define RTL8367_PORT_0 BIT(0) 230#define RTL8367_PORT_1 BIT(1) 231#define RTL8367_PORT_2 BIT(2) 232#define RTL8367_PORT_3 BIT(3) 233#define RTL8367_PORT_4 BIT(4) 234#define RTL8367_PORT_5 BIT(5) 235#define RTL8367_PORT_6 BIT(6) 236#define RTL8367_PORT_7 BIT(7) 237#define RTL8367_PORT_E1 BIT(8) /* external port 1 */ 238#define RTL8367_PORT_E0 BIT(9) /* external port 0 */ 239 240#define RTL8367_PORTS_ALL \ 241 (RTL8367_PORT_0 | RTL8367_PORT_1 | RTL8367_PORT_2 | \ 242 RTL8367_PORT_3 | RTL8367_PORT_4 | RTL8367_PORT_5 | \ 243 RTL8367_PORT_6 | RTL8367_PORT_7 | RTL8367_PORT_E1 | \ 244 RTL8367_PORT_E0) 245 246#define RTL8367_PORTS_ALL_BUT_CPU \ 247 (RTL8367_PORT_0 | RTL8367_PORT_1 | RTL8367_PORT_2 | \ 248 RTL8367_PORT_3 | RTL8367_PORT_4 | RTL8367_PORT_5 | \ 249 RTL8367_PORT_6 | RTL8367_PORT_7 | RTL8367_PORT_E1) 250 251struct rtl8367_initval { 252 u16 reg; 253 u16 val; 254}; 255 256static struct rtl8366_mib_counter rtl8367_mib_counters[] = { 257 { 0, 0, 4, "IfInOctets" }, 258 { 0, 4, 2, "Dot3StatsFCSErrors" }, 259 { 0, 6, 2, "Dot3StatsSymbolErrors" }, 260 { 0, 8, 2, "Dot3InPauseFrames" }, 261 { 0, 10, 2, "Dot3ControlInUnknownOpcodes" }, 262 { 0, 12, 2, "EtherStatsFragments" }, 263 { 0, 14, 2, "EtherStatsJabbers" }, 264 { 0, 16, 2, "IfInUcastPkts" }, 265 { 0, 18, 2, "EtherStatsDropEvents" }, 266 { 0, 20, 4, "EtherStatsOctets" }, 267 268 { 0, 24, 2, "EtherStatsUnderSizePkts" }, 269 { 0, 26, 2, "EtherOversizeStats" }, 270 { 0, 28, 2, "EtherStatsPkts64Octets" }, 271 { 0, 30, 2, "EtherStatsPkts65to127Octets" }, 272 { 0, 32, 2, "EtherStatsPkts128to255Octets" }, 273 { 0, 34, 2, "EtherStatsPkts256to511Octets" }, 274 { 0, 36, 2, "EtherStatsPkts512to1023Octets" }, 275 { 0, 38, 2, "EtherStatsPkts1024to1518Octets" }, 276 { 0, 40, 2, "EtherStatsMulticastPkts" }, 277 { 0, 42, 2, "EtherStatsBroadcastPkts" }, 278 279 { 0, 44, 4, "IfOutOctets" }, 280 281 { 0, 48, 2, "Dot3StatsSingleCollisionFrames" }, 282 { 0, 50, 2, "Dot3StatMultipleCollisionFrames" }, 283 { 0, 52, 2, "Dot3sDeferredTransmissions" }, 284 { 0, 54, 2, "Dot3StatsLateCollisions" }, 285 { 0, 56, 2, "EtherStatsCollisions" }, 286 { 0, 58, 2, "Dot3StatsExcessiveCollisions" }, 287 { 0, 60, 2, "Dot3OutPauseFrames" }, 288 { 0, 62, 2, "Dot1dBasePortDelayExceededDiscards" }, 289 { 0, 64, 2, "Dot1dTpPortInDiscards" }, 290 { 0, 66, 2, "IfOutUcastPkts" }, 291 { 0, 68, 2, "IfOutMulticastPkts" }, 292 { 0, 70, 2, "IfOutBroadcastPkts" }, 293 { 0, 72, 2, "OutOampduPkts" }, 294 { 0, 74, 2, "InOampduPkts" }, 295 { 0, 76, 2, "PktgenPkts" }, 296}; 297 298#define REG_RD(_smi, _reg, _val) \ 299 do { \ 300 err = rtl8366_smi_read_reg(_smi, _reg, _val); \ 301 if (err) \ 302 return err; \ 303 } while (0) 304 305#define REG_WR(_smi, _reg, _val) \ 306 do { \ 307 err = rtl8366_smi_write_reg(_smi, _reg, _val); \ 308 if (err) \ 309 return err; \ 310 } while (0) 311 312#define REG_RMW(_smi, _reg, _mask, _val) \ 313 do { \ 314 err = rtl8366_smi_rmwr(_smi, _reg, _mask, _val); \ 315 if (err) \ 316 return err; \ 317 } while (0) 318 319static const struct rtl8367_initval rtl8367_initvals_0_0[] = { 320 {0x133f, 0x0030}, {0x133e, 0x000e}, {0x221f, 0x0000}, {0x2215, 0x1006}, 321 {0x221f, 0x0005}, {0x2200, 0x00c6}, {0x221f, 0x0007}, {0x221e, 0x0048}, 322 {0x2215, 0x6412}, {0x2216, 0x6412}, {0x2217, 0x6412}, {0x2218, 0x6412}, 323 {0x2219, 0x6412}, {0x221A, 0x6412}, {0x221f, 0x0001}, {0x220c, 0xdbf0}, 324 {0x2209, 0x2576}, {0x2207, 0x287E}, {0x220A, 0x68E5}, {0x221D, 0x3DA4}, 325 {0x221C, 0xE7F7}, {0x2214, 0x7F52}, {0x2218, 0x7FCE}, {0x2208, 0x04B7}, 326 {0x2206, 0x4072}, {0x2210, 0xF05E}, {0x221B, 0xB414}, {0x221F, 0x0003}, 327 {0x221A, 0x06A6}, {0x2210, 0xF05E}, {0x2213, 0x06EB}, {0x2212, 0xF4D2}, 328 {0x220E, 0xE120}, {0x2200, 0x7C00}, {0x2202, 0x5FD0}, {0x220D, 0x0207}, 329 {0x221f, 0x0002}, {0x2205, 0x0978}, {0x2202, 0x8C01}, {0x2207, 0x3620}, 330 {0x221C, 0x0001}, {0x2203, 0x0420}, {0x2204, 0x80C8}, {0x133e, 0x0ede}, 331 {0x221f, 0x0002}, {0x220c, 0x0073}, {0x220d, 0xEB65}, {0x220e, 0x51d1}, 332 {0x220f, 0x5dcb}, {0x2210, 0x3044}, {0x2211, 0x1800}, {0x2212, 0x7E00}, 333 {0x2213, 0x0000}, {0x133f, 0x0010}, {0x133e, 0x0ffe}, {0x207f, 0x0002}, 334 {0x2074, 0x3D22}, {0x2075, 0x2000}, {0x2076, 0x6040}, {0x2077, 0x0000}, 335 {0x2078, 0x0f0a}, {0x2079, 0x50AB}, {0x207a, 0x0000}, {0x207b, 0x0f0f}, 336 {0x205f, 0x0002}, {0x2054, 0xFF00}, {0x2055, 0x000A}, {0x2056, 0x000A}, 337 {0x2057, 0x0005}, {0x2058, 0x0005}, {0x2059, 0x0000}, {0x205A, 0x0005}, 338 {0x205B, 0x0005}, {0x205C, 0x0005}, {0x209f, 0x0002}, {0x2094, 0x00AA}, 339 {0x2095, 0x00AA}, {0x2096, 0x00AA}, {0x2097, 0x00AA}, {0x2098, 0x0055}, 340 {0x2099, 0x00AA}, {0x209A, 0x00AA}, {0x209B, 0x00AA}, {0x1363, 0x8354}, 341 {0x1270, 0x3333}, {0x1271, 0x3333}, {0x1272, 0x3333}, {0x1330, 0x00DB}, 342 {0x1203, 0xff00}, {0x1200, 0x7fc4}, {0x121d, 0x1006}, {0x121e, 0x03e8}, 343 {0x121f, 0x02b3}, {0x1220, 0x028f}, {0x1221, 0x029b}, {0x1222, 0x0277}, 344 {0x1223, 0x02b3}, {0x1224, 0x028f}, {0x1225, 0x029b}, {0x1226, 0x0277}, 345 {0x1227, 0x00c0}, {0x1228, 0x00b4}, {0x122f, 0x00c0}, {0x1230, 0x00b4}, 346 {0x1229, 0x0020}, {0x122a, 0x000c}, {0x1231, 0x0030}, {0x1232, 0x0024}, 347 {0x0219, 0x0032}, {0x0200, 0x03e8}, {0x0201, 0x03e8}, {0x0202, 0x03e8}, 348 {0x0203, 0x03e8}, {0x0204, 0x03e8}, {0x0205, 0x03e8}, {0x0206, 0x03e8}, 349 {0x0207, 0x03e8}, {0x0218, 0x0032}, {0x0208, 0x029b}, {0x0209, 0x029b}, 350 {0x020a, 0x029b}, {0x020b, 0x029b}, {0x020c, 0x029b}, {0x020d, 0x029b}, 351 {0x020e, 0x029b}, {0x020f, 0x029b}, {0x0210, 0x029b}, {0x0211, 0x029b}, 352 {0x0212, 0x029b}, {0x0213, 0x029b}, {0x0214, 0x029b}, {0x0215, 0x029b}, 353 {0x0216, 0x029b}, {0x0217, 0x029b}, {0x0900, 0x0000}, {0x0901, 0x0000}, 354 {0x0902, 0x0000}, {0x0903, 0x0000}, {0x0865, 0x3210}, {0x087b, 0x0000}, 355 {0x087c, 0xff00}, {0x087d, 0x0000}, {0x087e, 0x0000}, {0x0801, 0x0100}, 356 {0x0802, 0x0100}, {0x1700, 0x014C}, {0x0301, 0x00FF}, {0x12AA, 0x0096}, 357 {0x133f, 0x0030}, {0x133e, 0x000e}, {0x221f, 0x0005}, {0x2200, 0x00C4}, 358 {0x221f, 0x0000}, {0x2210, 0x05EF}, {0x2204, 0x05E1}, {0x2200, 0x1340}, 359 {0x133f, 0x0010}, {0x20A0, 0x1940}, {0x20C0, 0x1940}, {0x20E0, 0x1940}, 360}; 361 362static const struct rtl8367_initval rtl8367_initvals_0_1[] = { 363 {0x133f, 0x0030}, {0x133e, 0x000e}, {0x221f, 0x0000}, {0x2215, 0x1006}, 364 {0x221f, 0x0005}, {0x2200, 0x00c6}, {0x221f, 0x0007}, {0x221e, 0x0048}, 365 {0x2215, 0x6412}, {0x2216, 0x6412}, {0x2217, 0x6412}, {0x2218, 0x6412}, 366 {0x2219, 0x6412}, {0x221A, 0x6412}, {0x221f, 0x0001}, {0x220c, 0xdbf0}, 367 {0x2209, 0x2576}, {0x2207, 0x287E}, {0x220A, 0x68E5}, {0x221D, 0x3DA4}, 368 {0x221C, 0xE7F7}, {0x2214, 0x7F52}, {0x2218, 0x7FCE}, {0x2208, 0x04B7}, 369 {0x2206, 0x4072}, {0x2210, 0xF05E}, {0x221B, 0xB414}, {0x221F, 0x0003}, 370 {0x221A, 0x06A6}, {0x2210, 0xF05E}, {0x2213, 0x06EB}, {0x2212, 0xF4D2}, 371 {0x220E, 0xE120}, {0x2200, 0x7C00}, {0x2202, 0x5FD0}, {0x220D, 0x0207}, 372 {0x221f, 0x0002}, {0x2205, 0x0978}, {0x2202, 0x8C01}, {0x2207, 0x3620}, 373 {0x221C, 0x0001}, {0x2203, 0x0420}, {0x2204, 0x80C8}, {0x133e, 0x0ede}, 374 {0x221f, 0x0002}, {0x220c, 0x0073}, {0x220d, 0xEB65}, {0x220e, 0x51d1}, 375 {0x220f, 0x5dcb}, {0x2210, 0x3044}, {0x2211, 0x1800}, {0x2212, 0x7E00}, 376 {0x2213, 0x0000}, {0x133f, 0x0010}, {0x133e, 0x0ffe}, {0x207f, 0x0002}, 377 {0x2074, 0x3D22}, {0x2075, 0x2000}, {0x2076, 0x6040}, {0x2077, 0x0000}, 378 {0x2078, 0x0f0a}, {0x2079, 0x50AB}, {0x207a, 0x0000}, {0x207b, 0x0f0f}, 379 {0x205f, 0x0002}, {0x2054, 0xFF00}, {0x2055, 0x000A}, {0x2056, 0x000A}, 380 {0x2057, 0x0005}, {0x2058, 0x0005}, {0x2059, 0x0000}, {0x205A, 0x0005}, 381 {0x205B, 0x0005}, {0x205C, 0x0005}, {0x209f, 0x0002}, {0x2094, 0x00AA}, 382 {0x2095, 0x00AA}, {0x2096, 0x00AA}, {0x2097, 0x00AA}, {0x2098, 0x0055}, 383 {0x2099, 0x00AA}, {0x209A, 0x00AA}, {0x209B, 0x00AA}, {0x1363, 0x8354}, 384 {0x1270, 0x3333}, {0x1271, 0x3333}, {0x1272, 0x3333}, {0x1330, 0x00DB}, 385 {0x1203, 0xff00}, {0x1200, 0x7fc4}, {0x121d, 0x1b06}, {0x121e, 0x07f0}, 386 {0x121f, 0x0438}, {0x1220, 0x040f}, {0x1221, 0x040f}, {0x1222, 0x03eb}, 387 {0x1223, 0x0438}, {0x1224, 0x040f}, {0x1225, 0x040f}, {0x1226, 0x03eb}, 388 {0x1227, 0x0144}, {0x1228, 0x0138}, {0x122f, 0x0144}, {0x1230, 0x0138}, 389 {0x1229, 0x0020}, {0x122a, 0x000c}, {0x1231, 0x0030}, {0x1232, 0x0024}, 390 {0x0219, 0x0032}, {0x0200, 0x07d0}, {0x0201, 0x07d0}, {0x0202, 0x07d0}, 391 {0x0203, 0x07d0}, {0x0204, 0x07d0}, {0x0205, 0x07d0}, {0x0206, 0x07d0}, 392 {0x0207, 0x07d0}, {0x0218, 0x0032}, {0x0208, 0x0190}, {0x0209, 0x0190}, 393 {0x020a, 0x0190}, {0x020b, 0x0190}, {0x020c, 0x0190}, {0x020d, 0x0190}, 394 {0x020e, 0x0190}, {0x020f, 0x0190}, {0x0210, 0x0190}, {0x0211, 0x0190}, 395 {0x0212, 0x0190}, {0x0213, 0x0190}, {0x0214, 0x0190}, {0x0215, 0x0190}, 396 {0x0216, 0x0190}, {0x0217, 0x0190}, {0x0900, 0x0000}, {0x0901, 0x0000}, 397 {0x0902, 0x0000}, {0x0903, 0x0000}, {0x0865, 0x3210}, {0x087b, 0x0000}, 398 {0x087c, 0xff00}, {0x087d, 0x0000}, {0x087e, 0x0000}, {0x0801, 0x0100}, 399 {0x0802, 0x0100}, {0x1700, 0x0125}, {0x0301, 0x00FF}, {0x12AA, 0x0096}, 400 {0x133f, 0x0030}, {0x133e, 0x000e}, {0x221f, 0x0005}, {0x2200, 0x00C4}, 401 {0x221f, 0x0000}, {0x2210, 0x05EF}, {0x2204, 0x05E1}, {0x2200, 0x1340}, 402 {0x133f, 0x0010}, 403}; 404 405static const struct rtl8367_initval rtl8367_initvals_1_0[] = { 406 {0x1B24, 0x0000}, {0x1B25, 0x0000}, {0x1B26, 0x0000}, {0x1B27, 0x0000}, 407 {0x207F, 0x0002}, {0x2079, 0x0200}, {0x207F, 0x0000}, {0x133F, 0x0030}, 408 {0x133E, 0x000E}, {0x221F, 0x0005}, {0x2201, 0x0700}, {0x2205, 0x8B82}, 409 {0x2206, 0x05CB}, {0x221F, 0x0002}, {0x2204, 0x80C2}, {0x2205, 0x0938}, 410 {0x221F, 0x0003}, {0x2212, 0xC4D2}, {0x220D, 0x0207}, {0x221F, 0x0001}, 411 {0x2207, 0x267E}, {0x221C, 0xE5F7}, {0x221B, 0x0424}, {0x221F, 0x0007}, 412 {0x221E, 0x0040}, {0x2218, 0x0000}, {0x221F, 0x0007}, {0x221E, 0x002C}, 413 {0x2218, 0x008B}, {0x221F, 0x0005}, {0x2205, 0xFFF6}, {0x2206, 0x0080}, 414 {0x2205, 0x8000}, {0x2206, 0xF8E0}, {0x2206, 0xE000}, {0x2206, 0xE1E0}, 415 {0x2206, 0x01AC}, {0x2206, 0x2408}, {0x2206, 0xE08B}, {0x2206, 0x84F7}, 416 {0x2206, 0x20E4}, {0x2206, 0x8B84}, {0x2206, 0xFC05}, {0x2206, 0xF8FA}, 417 {0x2206, 0xEF69}, {0x2206, 0xE08B}, {0x2206, 0x86AC}, {0x2206, 0x201A}, 418 {0x2206, 0xBF80}, {0x2206, 0x59D0}, {0x2206, 0x2402}, {0x2206, 0x803D}, 419 {0x2206, 0xE0E0}, {0x2206, 0xE4E1}, {0x2206, 0xE0E5}, {0x2206, 0x5806}, 420 {0x2206, 0x68C0}, {0x2206, 0xD1D2}, {0x2206, 0xE4E0}, {0x2206, 0xE4E5}, 421 {0x2206, 0xE0E5}, {0x2206, 0xEF96}, {0x2206, 0xFEFC}, {0x2206, 0x05FB}, 422 {0x2206, 0x0BFB}, {0x2206, 0x58FF}, {0x2206, 0x9E11}, {0x2206, 0x06F0}, 423 {0x2206, 0x0C81}, {0x2206, 0x8AE0}, {0x2206, 0x0019}, {0x2206, 0x1B89}, 424 {0x2206, 0xCFEB}, {0x2206, 0x19EB}, {0x2206, 0x19B0}, {0x2206, 0xEFFF}, 425 {0x2206, 0x0BFF}, {0x2206, 0x0425}, {0x2206, 0x0807}, {0x2206, 0x2640}, 426 {0x2206, 0x7227}, {0x2206, 0x267E}, {0x2206, 0x2804}, {0x2206, 0xB729}, 427 {0x2206, 0x2576}, {0x2206, 0x2A68}, {0x2206, 0xE52B}, {0x2206, 0xAD00}, 428 {0x2206, 0x2CDB}, {0x2206, 0xF02D}, {0x2206, 0x67BB}, {0x2206, 0x2E7B}, 429 {0x2206, 0x0F2F}, {0x2206, 0x7365}, {0x2206, 0x31AC}, {0x2206, 0xCC32}, 430 {0x2206, 0x2300}, {0x2206, 0x332D}, {0x2206, 0x1734}, {0x2206, 0x7F52}, 431 {0x2206, 0x3510}, {0x2206, 0x0036}, {0x2206, 0x0600}, {0x2206, 0x370C}, 432 {0x2206, 0xC038}, {0x2206, 0x7FCE}, {0x2206, 0x3CE5}, {0x2206, 0xF73D}, 433 {0x2206, 0x3DA4}, {0x2206, 0x6530}, {0x2206, 0x3E67}, {0x2206, 0x0053}, 434 {0x2206, 0x69D2}, {0x2206, 0x0F6A}, {0x2206, 0x012C}, {0x2206, 0x6C2B}, 435 {0x2206, 0x136E}, {0x2206, 0xE100}, {0x2206, 0x6F12}, {0x2206, 0xF771}, 436 {0x2206, 0x006B}, {0x2206, 0x7306}, {0x2206, 0xEB74}, {0x2206, 0x94C7}, 437 {0x2206, 0x7698}, {0x2206, 0x0A77}, {0x2206, 0x5000}, {0x2206, 0x788A}, 438 {0x2206, 0x1579}, {0x2206, 0x7F6F}, {0x2206, 0x7A06}, {0x2206, 0xA600}, 439 {0x2205, 0x8B90}, {0x2206, 0x8000}, {0x2205, 0x8B92}, {0x2206, 0x8000}, 440 {0x2205, 0x8B94}, {0x2206, 0x8014}, {0x2208, 0xFFFA}, {0x2202, 0x3C65}, 441 {0x2205, 0xFFF6}, {0x2206, 0x00F7}, {0x221F, 0x0000}, {0x221F, 0x0007}, 442 {0x221E, 0x0042}, {0x2218, 0x0000}, {0x221E, 0x002D}, {0x2218, 0xF010}, 443 {0x221E, 0x0020}, {0x2215, 0x0000}, {0x221E, 0x0023}, {0x2216, 0x8000}, 444 {0x221F, 0x0000}, {0x133F, 0x0010}, {0x133E, 0x0FFE}, {0x1362, 0x0115}, 445 {0x1363, 0x0002}, {0x1363, 0x0000}, {0x1306, 0x000C}, {0x1307, 0x000C}, 446 {0x1303, 0x0067}, {0x1304, 0x4444}, {0x1203, 0xFF00}, {0x1200, 0x7FC4}, 447 {0x121D, 0x7D16}, {0x121E, 0x03E8}, {0x121F, 0x024E}, {0x1220, 0x0230}, 448 {0x1221, 0x0244}, {0x1222, 0x0226}, {0x1223, 0x024E}, {0x1224, 0x0230}, 449 {0x1225, 0x0244}, {0x1226, 0x0226}, {0x1227, 0x00C0}, {0x1228, 0x00B4}, 450 {0x122F, 0x00C0}, {0x1230, 0x00B4}, {0x0208, 0x03E8}, {0x0209, 0x03E8}, 451 {0x020A, 0x03E8}, {0x020B, 0x03E8}, {0x020C, 0x03E8}, {0x020D, 0x03E8}, 452 {0x020E, 0x03E8}, {0x020F, 0x03E8}, {0x0210, 0x03E8}, {0x0211, 0x03E8}, 453 {0x0212, 0x03E8}, {0x0213, 0x03E8}, {0x0214, 0x03E8}, {0x0215, 0x03E8}, 454 {0x0216, 0x03E8}, {0x0217, 0x03E8}, {0x0900, 0x0000}, {0x0901, 0x0000}, 455 {0x0902, 0x0000}, {0x0903, 0x0000}, {0x0865, 0x3210}, {0x087B, 0x0000}, 456 {0x087C, 0xFF00}, {0x087D, 0x0000}, {0x087E, 0x0000}, {0x0801, 0x0100}, 457 {0x0802, 0x0100}, {0x0A20, 0x2040}, {0x0A21, 0x2040}, {0x0A22, 0x2040}, 458 {0x0A23, 0x2040}, {0x0A24, 0x2040}, {0x0A28, 0x2040}, {0x0A29, 0x2040}, 459 {0x133F, 0x0030}, {0x133E, 0x000E}, {0x221F, 0x0000}, {0x2200, 0x1340}, 460 {0x221F, 0x0000}, {0x133F, 0x0010}, {0x133E, 0x0FFE}, {0x20A0, 0x1940}, 461 {0x20C0, 0x1940}, {0x20E0, 0x1940}, {0x130c, 0x0050}, 462}; 463 464static const struct rtl8367_initval rtl8367_initvals_1_1[] = { 465 {0x1B24, 0x0000}, {0x1B25, 0x0000}, {0x1B26, 0x0000}, {0x1B27, 0x0000}, 466 {0x207F, 0x0002}, {0x2079, 0x0200}, {0x207F, 0x0000}, {0x133F, 0x0030}, 467 {0x133E, 0x000E}, {0x221F, 0x0005}, {0x2201, 0x0700}, {0x2205, 0x8B82}, 468 {0x2206, 0x05CB}, {0x221F, 0x0002}, {0x2204, 0x80C2}, {0x2205, 0x0938}, 469 {0x221F, 0x0003}, {0x2212, 0xC4D2}, {0x220D, 0x0207}, {0x221F, 0x0001}, 470 {0x2207, 0x267E}, {0x221C, 0xE5F7}, {0x221B, 0x0424}, {0x221F, 0x0007}, 471 {0x221E, 0x0040}, {0x2218, 0x0000}, {0x221F, 0x0007}, {0x221E, 0x002C}, 472 {0x2218, 0x008B}, {0x221F, 0x0005}, {0x2205, 0xFFF6}, {0x2206, 0x0080}, 473 {0x2205, 0x8000}, {0x2206, 0xF8E0}, {0x2206, 0xE000}, {0x2206, 0xE1E0}, 474 {0x2206, 0x01AC}, {0x2206, 0x2408}, {0x2206, 0xE08B}, {0x2206, 0x84F7}, 475 {0x2206, 0x20E4}, {0x2206, 0x8B84}, {0x2206, 0xFC05}, {0x2206, 0xF8FA}, 476 {0x2206, 0xEF69}, {0x2206, 0xE08B}, {0x2206, 0x86AC}, {0x2206, 0x201A}, 477 {0x2206, 0xBF80}, {0x2206, 0x59D0}, {0x2206, 0x2402}, {0x2206, 0x803D}, 478 {0x2206, 0xE0E0}, {0x2206, 0xE4E1}, {0x2206, 0xE0E5}, {0x2206, 0x5806}, 479 {0x2206, 0x68C0}, {0x2206, 0xD1D2}, {0x2206, 0xE4E0}, {0x2206, 0xE4E5}, 480 {0x2206, 0xE0E5}, {0x2206, 0xEF96}, {0x2206, 0xFEFC}, {0x2206, 0x05FB}, 481 {0x2206, 0x0BFB}, {0x2206, 0x58FF}, {0x2206, 0x9E11}, {0x2206, 0x06F0}, 482 {0x2206, 0x0C81}, {0x2206, 0x8AE0}, {0x2206, 0x0019}, {0x2206, 0x1B89}, 483 {0x2206, 0xCFEB}, {0x2206, 0x19EB}, {0x2206, 0x19B0}, {0x2206, 0xEFFF}, 484 {0x2206, 0x0BFF}, {0x2206, 0x0425}, {0x2206, 0x0807}, {0x2206, 0x2640}, 485 {0x2206, 0x7227}, {0x2206, 0x267E}, {0x2206, 0x2804}, {0x2206, 0xB729}, 486 {0x2206, 0x2576}, {0x2206, 0x2A68}, {0x2206, 0xE52B}, {0x2206, 0xAD00}, 487 {0x2206, 0x2CDB}, {0x2206, 0xF02D}, {0x2206, 0x67BB}, {0x2206, 0x2E7B}, 488 {0x2206, 0x0F2F}, {0x2206, 0x7365}, {0x2206, 0x31AC}, {0x2206, 0xCC32}, 489 {0x2206, 0x2300}, {0x2206, 0x332D}, {0x2206, 0x1734}, {0x2206, 0x7F52}, 490 {0x2206, 0x3510}, {0x2206, 0x0036}, {0x2206, 0x0600}, {0x2206, 0x370C}, 491 {0x2206, 0xC038}, {0x2206, 0x7FCE}, {0x2206, 0x3CE5}, {0x2206, 0xF73D}, 492 {0x2206, 0x3DA4}, {0x2206, 0x6530}, {0x2206, 0x3E67}, {0x2206, 0x0053}, 493 {0x2206, 0x69D2}, {0x2206, 0x0F6A}, {0x2206, 0x012C}, {0x2206, 0x6C2B}, 494 {0x2206, 0x136E}, {0x2206, 0xE100}, {0x2206, 0x6F12}, {0x2206, 0xF771}, 495 {0x2206, 0x006B}, {0x2206, 0x7306}, {0x2206, 0xEB74}, {0x2206, 0x94C7}, 496 {0x2206, 0x7698}, {0x2206, 0x0A77}, {0x2206, 0x5000}, {0x2206, 0x788A}, 497 {0x2206, 0x1579}, {0x2206, 0x7F6F}, {0x2206, 0x7A06}, {0x2206, 0xA600}, 498 {0x2205, 0x8B90}, {0x2206, 0x8000}, {0x2205, 0x8B92}, {0x2206, 0x8000}, 499 {0x2205, 0x8B94}, {0x2206, 0x8014}, {0x2208, 0xFFFA}, {0x2202, 0x3C65}, 500 {0x2205, 0xFFF6}, {0x2206, 0x00F7}, {0x221F, 0x0000}, {0x221F, 0x0007}, 501 {0x221E, 0x0042}, {0x2218, 0x0000}, {0x221E, 0x002D}, {0x2218, 0xF010}, 502 {0x221E, 0x0020}, {0x2215, 0x0000}, {0x221E, 0x0023}, {0x2216, 0x8000}, 503 {0x221F, 0x0000}, {0x133F, 0x0010}, {0x133E, 0x0FFE}, {0x1362, 0x0115}, 504 {0x1363, 0x0002}, {0x1363, 0x0000}, {0x1306, 0x000C}, {0x1307, 0x000C}, 505 {0x1303, 0x0067}, {0x1304, 0x4444}, {0x1203, 0xFF00}, {0x1200, 0x7FC4}, 506 {0x0900, 0x0000}, {0x0901, 0x0000}, {0x0902, 0x0000}, {0x0903, 0x0000}, 507 {0x0865, 0x3210}, {0x087B, 0x0000}, {0x087C, 0xFF00}, {0x087D, 0x0000}, 508 {0x087E, 0x0000}, {0x0801, 0x0100}, {0x0802, 0x0100}, {0x0A20, 0x2040}, 509 {0x0A21, 0x2040}, {0x0A22, 0x2040}, {0x0A23, 0x2040}, {0x0A24, 0x2040}, 510 {0x0A25, 0x2040}, {0x0A26, 0x2040}, {0x0A27, 0x2040}, {0x0A28, 0x2040}, 511 {0x0A29, 0x2040}, {0x133F, 0x0030}, {0x133E, 0x000E}, {0x221F, 0x0000}, 512 {0x2200, 0x1340}, {0x221F, 0x0000}, {0x133F, 0x0010}, {0x133E, 0x0FFE}, 513 {0x1B03, 0x0876}, 514}; 515 516static const struct rtl8367_initval rtl8367_initvals_2_0[] = { 517 {0x1b24, 0x0000}, {0x1b25, 0x0000}, {0x1b26, 0x0000}, {0x1b27, 0x0000}, 518 {0x133f, 0x0030}, {0x133e, 0x000e}, {0x221f, 0x0007}, {0x221e, 0x0048}, 519 {0x2219, 0x4012}, {0x221f, 0x0003}, {0x2201, 0x3554}, {0x2202, 0x63e8}, 520 {0x2203, 0x99c2}, {0x2204, 0x0113}, {0x2205, 0x303e}, {0x220d, 0x0207}, 521 {0x220e, 0xe100}, {0x221f, 0x0007}, {0x221e, 0x0040}, {0x2218, 0x0000}, 522 {0x221f, 0x0007}, {0x221e, 0x002c}, {0x2218, 0x008b}, {0x221f, 0x0005}, 523 {0x2205, 0xfff6}, {0x2206, 0x0080}, {0x221f, 0x0005}, {0x2205, 0x8000}, 524 {0x2206, 0x0280}, {0x2206, 0x2bf7}, {0x2206, 0x00e0}, {0x2206, 0xfff7}, 525 {0x2206, 0xa080}, {0x2206, 0x02ae}, {0x2206, 0xf602}, {0x2206, 0x804e}, 526 {0x2206, 0x0201}, {0x2206, 0x5002}, {0x2206, 0x0163}, {0x2206, 0x0201}, 527 {0x2206, 0x79e0}, {0x2206, 0x8b8c}, {0x2206, 0xe18b}, {0x2206, 0x8d1e}, 528 {0x2206, 0x01e1}, {0x2206, 0x8b8e}, {0x2206, 0x1e01}, {0x2206, 0xa000}, 529 {0x2206, 0xe4ae}, {0x2206, 0xd8bf}, {0x2206, 0x8b88}, {0x2206, 0xec00}, 530 {0x2206, 0x19a9}, {0x2206, 0x8b90}, {0x2206, 0xf9ee}, {0x2206, 0xfff6}, 531 {0x2206, 0x00ee}, {0x2206, 0xfff7}, {0x2206, 0xfce0}, {0x2206, 0xe140}, 532 {0x2206, 0xe1e1}, {0x2206, 0x41f7}, {0x2206, 0x2ff6}, {0x2206, 0x28e4}, 533 {0x2206, 0xe140}, {0x2206, 0xe5e1}, {0x2206, 0x4104}, {0x2206, 0xf8fa}, 534 {0x2206, 0xef69}, {0x2206, 0xe08b}, {0x2206, 0x86ac}, {0x2206, 0x201a}, 535 {0x2206, 0xbf80}, {0x2206, 0x77d0}, {0x2206, 0x6c02}, {0x2206, 0x2978}, 536 {0x2206, 0xe0e0}, {0x2206, 0xe4e1}, {0x2206, 0xe0e5}, {0x2206, 0x5806}, 537 {0x2206, 0x68c0}, {0x2206, 0xd1d2}, {0x2206, 0xe4e0}, {0x2206, 0xe4e5}, 538 {0x2206, 0xe0e5}, {0x2206, 0xef96}, {0x2206, 0xfefc}, {0x2206, 0x0425}, 539 {0x2206, 0x0807}, {0x2206, 0x2640}, {0x2206, 0x7227}, {0x2206, 0x267e}, 540 {0x2206, 0x2804}, {0x2206, 0xb729}, {0x2206, 0x2576}, {0x2206, 0x2a68}, 541 {0x2206, 0xe52b}, {0x2206, 0xad00}, {0x2206, 0x2cdb}, {0x2206, 0xf02d}, 542 {0x2206, 0x67bb}, {0x2206, 0x2e7b}, {0x2206, 0x0f2f}, {0x2206, 0x7365}, 543 {0x2206, 0x31ac}, {0x2206, 0xcc32}, {0x2206, 0x2300}, {0x2206, 0x332d}, 544 {0x2206, 0x1734}, {0x2206, 0x7f52}, {0x2206, 0x3510}, {0x2206, 0x0036}, 545 {0x2206, 0x0600}, {0x2206, 0x370c}, {0x2206, 0xc038}, {0x2206, 0x7fce}, 546 {0x2206, 0x3ce5}, {0x2206, 0xf73d}, {0x2206, 0x3da4}, {0x2206, 0x6530}, 547 {0x2206, 0x3e67}, {0x2206, 0x0053}, {0x2206, 0x69d2}, {0x2206, 0x0f6a}, 548 {0x2206, 0x012c}, {0x2206, 0x6c2b}, {0x2206, 0x136e}, {0x2206, 0xe100}, 549 {0x2206, 0x6f12}, {0x2206, 0xf771}, {0x2206, 0x006b}, {0x2206, 0x7306}, 550 {0x2206, 0xeb74}, {0x2206, 0x94c7}, {0x2206, 0x7698}, {0x2206, 0x0a77}, 551 {0x2206, 0x5000}, {0x2206, 0x788a}, {0x2206, 0x1579}, {0x2206, 0x7f6f}, 552 {0x2206, 0x7a06}, {0x2206, 0xa600}, {0x2201, 0x0701}, {0x2200, 0x0405}, 553 {0x221f, 0x0000}, {0x2200, 0x1340}, {0x221f, 0x0000}, {0x133f, 0x0010}, 554 {0x133e, 0x0ffe}, {0x1203, 0xff00}, {0x1200, 0x7fc4}, {0x121d, 0x7D16}, 555 {0x121e, 0x03e8}, {0x121f, 0x024e}, {0x1220, 0x0230}, {0x1221, 0x0244}, 556 {0x1222, 0x0226}, {0x1223, 0x024e}, {0x1224, 0x0230}, {0x1225, 0x0244}, 557 {0x1226, 0x0226}, {0x1227, 0x00c0}, {0x1228, 0x00b4}, {0x122f, 0x00c0}, 558 {0x1230, 0x00b4}, {0x0208, 0x03e8}, {0x0209, 0x03e8}, {0x020a, 0x03e8}, 559 {0x020b, 0x03e8}, {0x020c, 0x03e8}, {0x020d, 0x03e8}, {0x020e, 0x03e8}, 560 {0x020f, 0x03e8}, {0x0210, 0x03e8}, {0x0211, 0x03e8}, {0x0212, 0x03e8}, 561 {0x0213, 0x03e8}, {0x0214, 0x03e8}, {0x0215, 0x03e8}, {0x0216, 0x03e8}, 562 {0x0217, 0x03e8}, {0x0900, 0x0000}, {0x0901, 0x0000}, {0x0902, 0x0000}, 563 {0x0903, 0x0000}, {0x0865, 0x3210}, {0x087b, 0x0000}, {0x087c, 0xff00}, 564 {0x087d, 0x0000}, {0x087e, 0x0000}, {0x0801, 0x0100}, {0x0802, 0x0100}, 565 {0x0A20, 0x2040}, {0x0A21, 0x2040}, {0x0A22, 0x2040}, {0x0A23, 0x2040}, 566 {0x0A24, 0x2040}, {0x0A28, 0x2040}, {0x0A29, 0x2040}, {0x20A0, 0x1940}, 567 {0x20C0, 0x1940}, {0x20E0, 0x1940}, {0x130c, 0x0050}, 568}; 569 570static const struct rtl8367_initval rtl8367_initvals_2_1[] = { 571 {0x1b24, 0x0000}, {0x1b25, 0x0000}, {0x1b26, 0x0000}, {0x1b27, 0x0000}, 572 {0x133f, 0x0030}, {0x133e, 0x000e}, {0x221f, 0x0007}, {0x221e, 0x0048}, 573 {0x2219, 0x4012}, {0x221f, 0x0003}, {0x2201, 0x3554}, {0x2202, 0x63e8}, 574 {0x2203, 0x99c2}, {0x2204, 0x0113}, {0x2205, 0x303e}, {0x220d, 0x0207}, 575 {0x220e, 0xe100}, {0x221f, 0x0007}, {0x221e, 0x0040}, {0x2218, 0x0000}, 576 {0x221f, 0x0007}, {0x221e, 0x002c}, {0x2218, 0x008b}, {0x221f, 0x0005}, 577 {0x2205, 0xfff6}, {0x2206, 0x0080}, {0x221f, 0x0005}, {0x2205, 0x8000}, 578 {0x2206, 0x0280}, {0x2206, 0x2bf7}, {0x2206, 0x00e0}, {0x2206, 0xfff7}, 579 {0x2206, 0xa080}, {0x2206, 0x02ae}, {0x2206, 0xf602}, {0x2206, 0x804e}, 580 {0x2206, 0x0201}, {0x2206, 0x5002}, {0x2206, 0x0163}, {0x2206, 0x0201}, 581 {0x2206, 0x79e0}, {0x2206, 0x8b8c}, {0x2206, 0xe18b}, {0x2206, 0x8d1e}, 582 {0x2206, 0x01e1}, {0x2206, 0x8b8e}, {0x2206, 0x1e01}, {0x2206, 0xa000}, 583 {0x2206, 0xe4ae}, {0x2206, 0xd8bf}, {0x2206, 0x8b88}, {0x2206, 0xec00}, 584 {0x2206, 0x19a9}, {0x2206, 0x8b90}, {0x2206, 0xf9ee}, {0x2206, 0xfff6}, 585 {0x2206, 0x00ee}, {0x2206, 0xfff7}, {0x2206, 0xfce0}, {0x2206, 0xe140}, 586 {0x2206, 0xe1e1}, {0x2206, 0x41f7}, {0x2206, 0x2ff6}, {0x2206, 0x28e4}, 587 {0x2206, 0xe140}, {0x2206, 0xe5e1}, {0x2206, 0x4104}, {0x2206, 0xf8fa}, 588 {0x2206, 0xef69}, {0x2206, 0xe08b}, {0x2206, 0x86ac}, {0x2206, 0x201a}, 589 {0x2206, 0xbf80}, {0x2206, 0x77d0}, {0x2206, 0x6c02}, {0x2206, 0x2978}, 590 {0x2206, 0xe0e0}, {0x2206, 0xe4e1}, {0x2206, 0xe0e5}, {0x2206, 0x5806}, 591 {0x2206, 0x68c0}, {0x2206, 0xd1d2}, {0x2206, 0xe4e0}, {0x2206, 0xe4e5}, 592 {0x2206, 0xe0e5}, {0x2206, 0xef96}, {0x2206, 0xfefc}, {0x2206, 0x0425}, 593 {0x2206, 0x0807}, {0x2206, 0x2640}, {0x2206, 0x7227}, {0x2206, 0x267e}, 594 {0x2206, 0x2804}, {0x2206, 0xb729}, {0x2206, 0x2576}, {0x2206, 0x2a68}, 595 {0x2206, 0xe52b}, {0x2206, 0xad00}, {0x2206, 0x2cdb}, {0x2206, 0xf02d}, 596 {0x2206, 0x67bb}, {0x2206, 0x2e7b}, {0x2206, 0x0f2f}, {0x2206, 0x7365}, 597 {0x2206, 0x31ac}, {0x2206, 0xcc32}, {0x2206, 0x2300}, {0x2206, 0x332d}, 598 {0x2206, 0x1734}, {0x2206, 0x7f52}, {0x2206, 0x3510}, {0x2206, 0x0036}, 599 {0x2206, 0x0600}, {0x2206, 0x370c}, {0x2206, 0xc038}, {0x2206, 0x7fce}, 600 {0x2206, 0x3ce5}, {0x2206, 0xf73d}, {0x2206, 0x3da4}, {0x2206, 0x6530}, 601 {0x2206, 0x3e67}, {0x2206, 0x0053}, {0x2206, 0x69d2}, {0x2206, 0x0f6a}, 602 {0x2206, 0x012c}, {0x2206, 0x6c2b}, {0x2206, 0x136e}, {0x2206, 0xe100}, 603 {0x2206, 0x6f12}, {0x2206, 0xf771}, {0x2206, 0x006b}, {0x2206, 0x7306}, 604 {0x2206, 0xeb74}, {0x2206, 0x94c7}, {0x2206, 0x7698}, {0x2206, 0x0a77}, 605 {0x2206, 0x5000}, {0x2206, 0x788a}, {0x2206, 0x1579}, {0x2206, 0x7f6f}, 606 {0x2206, 0x7a06}, {0x2206, 0xa600}, {0x2201, 0x0701}, {0x2200, 0x0405}, 607 {0x221f, 0x0000}, {0x2200, 0x1340}, {0x221f, 0x0000}, {0x133f, 0x0010}, 608 {0x133e, 0x0ffe}, {0x1203, 0xff00}, {0x1200, 0x7fc4}, {0x0900, 0x0000}, 609 {0x0901, 0x0000}, {0x0902, 0x0000}, {0x0903, 0x0000}, {0x0865, 0x3210}, 610 {0x087b, 0x0000}, {0x087c, 0xff00}, {0x087d, 0x0000}, {0x087e, 0x0000}, 611 {0x0801, 0x0100}, {0x0802, 0x0100}, {0x0A20, 0x2040}, {0x0A21, 0x2040}, 612 {0x0A22, 0x2040}, {0x0A23, 0x2040}, {0x0A24, 0x2040}, {0x0A25, 0x2040}, 613 {0x0A26, 0x2040}, {0x0A27, 0x2040}, {0x0A28, 0x2040}, {0x0A29, 0x2040}, 614 {0x130c, 0x0050}, 615}; 616 617static int rtl8367_write_initvals(struct rtl8366_smi *smi, 618 const struct rtl8367_initval *initvals, 619 int count) 620{ 621 int err; 622 int i; 623 624 for (i = 0; i < count; i++) 625 REG_WR(smi, initvals[i].reg, initvals[i].val); 626 627 return 0; 628} 629 630static int rtl8367_read_phy_reg(struct rtl8366_smi *smi, 631 u32 phy_addr, u32 phy_reg, u32 *val) 632{ 633 int timeout; 634 u32 data; 635 int err; 636 637 if (phy_addr > RTL8367_PHY_ADDR_MAX) 638 return -EINVAL; 639 640 if (phy_reg > RTL8367_PHY_REG_MAX) 641 return -EINVAL; 642 643 REG_RD(smi, RTL8367_IA_STATUS_REG, &data); 644 if (data & RTL8367_IA_STATUS_PHY_BUSY) 645 return -ETIMEDOUT; 646 647 /* prepare address */ 648 REG_WR(smi, RTL8367_IA_ADDRESS_REG, 649 RTL8367_INTERNAL_PHY_REG(phy_addr, phy_reg)); 650 651 /* send read command */ 652 REG_WR(smi, RTL8367_IA_CTRL_REG, 653 RTL8367_IA_CTRL_CMD_MASK | RTL8367_IA_CTRL_RW_READ); 654 655 timeout = 5; 656 do { 657 REG_RD(smi, RTL8367_IA_STATUS_REG, &data); 658 if ((data & RTL8367_IA_STATUS_PHY_BUSY) == 0) 659 break; 660 661 if (timeout--) { 662 dev_err(smi->parent, "phy read timed out\n"); 663 return -ETIMEDOUT; 664 } 665 666 udelay(1); 667 } while (1); 668 669 /* read data */ 670 REG_RD(smi, RTL8367_IA_READ_DATA_REG, val); 671 672 dev_dbg(smi->parent, "phy_read: addr:%02x, reg:%02x, val:%04x\n", 673 phy_addr, phy_reg, *val); 674 return 0; 675} 676 677static int rtl8367_write_phy_reg(struct rtl8366_smi *smi, 678 u32 phy_addr, u32 phy_reg, u32 val) 679{ 680 int timeout; 681 u32 data; 682 int err; 683 684 dev_dbg(smi->parent, "phy_write: addr:%02x, reg:%02x, val:%04x\n", 685 phy_addr, phy_reg, val); 686 687 if (phy_addr > RTL8367_PHY_ADDR_MAX) 688 return -EINVAL; 689 690 if (phy_reg > RTL8367_PHY_REG_MAX) 691 return -EINVAL; 692 693 REG_RD(smi, RTL8367_IA_STATUS_REG, &data); 694 if (data & RTL8367_IA_STATUS_PHY_BUSY) 695 return -ETIMEDOUT; 696 697 /* preapre data */ 698 REG_WR(smi, RTL8367_IA_WRITE_DATA_REG, val); 699 700 /* prepare address */ 701 REG_WR(smi, RTL8367_IA_ADDRESS_REG, 702 RTL8367_INTERNAL_PHY_REG(phy_addr, phy_reg)); 703 704 /* send write command */ 705 REG_WR(smi, RTL8367_IA_CTRL_REG, 706 RTL8367_IA_CTRL_CMD_MASK | RTL8367_IA_CTRL_RW_WRITE); 707 708 timeout = 5; 709 do { 710 REG_RD(smi, RTL8367_IA_STATUS_REG, &data); 711 if ((data & RTL8367_IA_STATUS_PHY_BUSY) == 0) 712 break; 713 714 if (timeout--) { 715 dev_err(smi->parent, "phy write timed out\n"); 716 return -ETIMEDOUT; 717 } 718 719 udelay(1); 720 } while (1); 721 722 return 0; 723} 724 725static int rtl8367_init_regs0(struct rtl8366_smi *smi, unsigned mode) 726{ 727 const struct rtl8367_initval *initvals; 728 int count; 729 int err; 730 731 switch (mode) { 732 case 0: 733 initvals = rtl8367_initvals_0_0; 734 count = ARRAY_SIZE(rtl8367_initvals_0_0); 735 break; 736 737 case 1: 738 case 2: 739 initvals = rtl8367_initvals_0_1; 740 count = ARRAY_SIZE(rtl8367_initvals_0_1); 741 break; 742 743 default: 744 dev_err(smi->parent, "%s: unknow mode %u\n", __func__, mode); 745 return -ENODEV; 746 } 747 748 err = rtl8367_write_initvals(smi, initvals, count); 749 if (err) 750 return err; 751 752 /* TODO: complete this */ 753 754 return 0; 755} 756 757static int rtl8367_init_regs1(struct rtl8366_smi *smi, unsigned mode) 758{ 759 const struct rtl8367_initval *initvals; 760 int count; 761 762 switch (mode) { 763 case 0: 764 initvals = rtl8367_initvals_1_0; 765 count = ARRAY_SIZE(rtl8367_initvals_1_0); 766 break; 767 768 case 1: 769 case 2: 770 initvals = rtl8367_initvals_1_1; 771 count = ARRAY_SIZE(rtl8367_initvals_1_1); 772 break; 773 774 default: 775 dev_err(smi->parent, "%s: unknow mode %u\n", __func__, mode); 776 return -ENODEV; 777 } 778 779 return rtl8367_write_initvals(smi, initvals, count); 780} 781 782static int rtl8367_init_regs2(struct rtl8366_smi *smi, unsigned mode) 783{ 784 const struct rtl8367_initval *initvals; 785 int count; 786 787 switch (mode) { 788 case 0: 789 initvals = rtl8367_initvals_2_0; 790 count = ARRAY_SIZE(rtl8367_initvals_2_0); 791 break; 792 793 case 1: 794 case 2: 795 initvals = rtl8367_initvals_2_1; 796 count = ARRAY_SIZE(rtl8367_initvals_2_1); 797 break; 798 799 default: 800 dev_err(smi->parent, "%s: unknow mode %u\n", __func__, mode); 801 return -ENODEV; 802 } 803 804 return rtl8367_write_initvals(smi, initvals, count); 805} 806 807static int rtl8367_init_regs(struct rtl8366_smi *smi) 808{ 809 u32 data; 810 u32 rlvid; 811 u32 mode; 812 int err; 813 814 REG_WR(smi, RTL8367_RTL_MAGIC_ID_REG, RTL8367_RTL_MAGIC_ID_VAL); 815 816 REG_RD(smi, RTL8367_CHIP_VER_REG, &data); 817 rlvid = (data >> RTL8367_CHIP_VER_RLVID_SHIFT) & 818 RTL8367_CHIP_VER_RLVID_MASK; 819 820 REG_RD(smi, RTL8367_CHIP_MODE_REG, &data); 821 mode = data & RTL8367_CHIP_MODE_MASK; 822 823 switch (rlvid) { 824 case 0: 825 err = rtl8367_init_regs0(smi, mode); 826 break; 827 828 case 1: 829 err = rtl8367_write_phy_reg(smi, 0, 31, 5); 830 if (err) 831 break; 832 833 err = rtl8367_write_phy_reg(smi, 0, 5, 0x3ffe); 834 if (err) 835 break; 836 837 err = rtl8367_read_phy_reg(smi, 0, 6, &data); 838 if (err) 839 break; 840 841 if (data == 0x94eb) { 842 err = rtl8367_init_regs1(smi, mode); 843 } else if (data == 0x2104) { 844 err = rtl8367_init_regs2(smi, mode); 845 } else { 846 dev_err(smi->parent, "unknow phy data %04x\n", data); 847 return -ENODEV; 848 } 849 850 break; 851 852 default: 853 dev_err(smi->parent, "unknow rlvid %u\n", rlvid); 854 err = -ENODEV; 855 break; 856 } 857 858 return err; 859} 860 861static int rtl8367_reset_chip(struct rtl8366_smi *smi) 862{ 863 int timeout = 10; 864 int err; 865 u32 data; 866 867 REG_WR(smi, RTL8367_CHIP_RESET_REG, RTL8367_CHIP_RESET_HW); 868 msleep(RTL8367_RESET_DELAY); 869 870 do { 871 REG_RD(smi, RTL8367_CHIP_RESET_REG, &data); 872 if (!(data & RTL8367_CHIP_RESET_HW)) 873 break; 874 875 msleep(1); 876 } while (--timeout); 877 878 if (!timeout) { 879 dev_err(smi->parent, "chip reset timed out\n"); 880 return -ETIMEDOUT; 881 } 882 883 return 0; 884} 885 886static int rtl8367_extif_set_mode(struct rtl8366_smi *smi, int id, 887 enum rtl8367_extif_mode mode) 888{ 889 int err; 890 891 /* set port mode */ 892 switch (mode) { 893 case RTL8367_EXTIF_MODE_RGMII: 894 case RTL8367_EXTIF_MODE_RGMII_33V: 895 REG_WR(smi, RTL8367_CHIP_DEBUG0_REG, 0x0367); 896 REG_WR(smi, RTL8367_CHIP_DEBUG1_REG, 0x7777); 897 break; 898 899 case RTL8367_EXTIF_MODE_TMII_MAC: 900 case RTL8367_EXTIF_MODE_TMII_PHY: 901 REG_RMW(smi, RTL8367_BYPASS_LINE_RATE_REG, 902 BIT((id + 1) % 2), BIT((id + 1) % 2)); 903 break; 904 905 case RTL8367_EXTIF_MODE_GMII: 906 REG_RMW(smi, RTL8367_CHIP_DEBUG0_REG, 907 RTL8367_CHIP_DEBUG0_DUMMY0(id), 908 RTL8367_CHIP_DEBUG0_DUMMY0(id)); 909 REG_RMW(smi, RTL8367_EXT_RGMXF_REG(id), BIT(6), BIT(6)); 910 break; 911 912 case RTL8367_EXTIF_MODE_MII_MAC: 913 case RTL8367_EXTIF_MODE_MII_PHY: 914 case RTL8367_EXTIF_MODE_DISABLED: 915 REG_RMW(smi, RTL8367_BYPASS_LINE_RATE_REG, 916 BIT((id + 1) % 2), 0); 917 REG_RMW(smi, RTL8367_EXT_RGMXF_REG(id), BIT(6), 0); 918 break; 919 920 default: 921 dev_err(smi->parent, 922 "invalid mode for external interface %d\n", id); 923 return -EINVAL; 924 } 925 926 REG_RMW(smi, RTL8367_DIS_REG, 927 RTL8367_DIS_RGMII_MASK << RTL8367_DIS_RGMII_SHIFT(id), 928 mode << RTL8367_DIS_RGMII_SHIFT(id)); 929 930 return 0; 931} 932 933static int rtl8367_extif_set_force(struct rtl8366_smi *smi, int id, 934 struct rtl8367_port_ability *pa) 935{ 936 u32 mask; 937 u32 val; 938 int err; 939 940 mask = (RTL8367_DI_FORCE_MODE | 941 RTL8367_DI_FORCE_NWAY | 942 RTL8367_DI_FORCE_TXPAUSE | 943 RTL8367_DI_FORCE_RXPAUSE | 944 RTL8367_DI_FORCE_LINK | 945 RTL8367_DI_FORCE_DUPLEX | 946 RTL8367_DI_FORCE_SPEED_MASK); 947 948 val = pa->speed; 949 val |= pa->force_mode ? RTL8367_DI_FORCE_MODE : 0; 950 val |= pa->nway ? RTL8367_DI_FORCE_NWAY : 0; 951 val |= pa->txpause ? RTL8367_DI_FORCE_TXPAUSE : 0; 952 val |= pa->rxpause ? RTL8367_DI_FORCE_RXPAUSE : 0; 953 val |= pa->link ? RTL8367_DI_FORCE_LINK : 0; 954 val |= pa->duplex ? RTL8367_DI_FORCE_DUPLEX : 0; 955 956 REG_RMW(smi, RTL8367_DI_FORCE_REG(id), mask, val); 957 958 return 0; 959} 960 961static int rtl8367_extif_set_rgmii_delay(struct rtl8366_smi *smi, int id, 962 unsigned txdelay, unsigned rxdelay) 963{ 964 u32 mask; 965 u32 val; 966 int err; 967 968 mask = (RTL8367_EXT_RGMXF_RXDELAY_MASK | 969 (RTL8367_EXT_RGMXF_TXDELAY_MASK << 970 RTL8367_EXT_RGMXF_TXDELAY_SHIFT)); 971 972 val = rxdelay; 973 val |= txdelay << RTL8367_EXT_RGMXF_TXDELAY_SHIFT; 974 975 REG_RMW(smi, RTL8367_EXT_RGMXF_REG(id), mask, val); 976 977 return 0; 978} 979 980static int rtl8367_extif_init(struct rtl8366_smi *smi, int id, 981 struct rtl8367_extif_config *cfg) 982{ 983 enum rtl8367_extif_mode mode; 984 int err; 985 986 mode = (cfg) ? cfg->mode : RTL8367_EXTIF_MODE_DISABLED; 987 988 err = rtl8367_extif_set_mode(smi, id, mode); 989 if (err) 990 return err; 991 992 if (mode != RTL8367_EXTIF_MODE_DISABLED) { 993 err = rtl8367_extif_set_force(smi, id, &cfg->ability); 994 if (err) 995 return err; 996 997 err = rtl8367_extif_set_rgmii_delay(smi, id, cfg->txdelay, 998 cfg->rxdelay); 999 if (err) 1000 return err; 1001 } 1002 1003 return 0; 1004} 1005 1006static int rtl8367_led_group_set_ports(struct rtl8366_smi *smi, 1007 unsigned int group, u16 port_mask) 1008{ 1009 u32 reg; 1010 u32 s; 1011 int err; 1012 1013 port_mask &= RTL8367_PARA_LED_IO_EN_PMASK; 1014 s = (group % 2) * 8; 1015 reg = RTL8367_PARA_LED_IO_EN1_REG + (group / 2); 1016 1017 REG_RMW(smi, reg, (RTL8367_PARA_LED_IO_EN_PMASK << s), port_mask << s); 1018 1019 return 0; 1020} 1021 1022static int rtl8367_led_group_set_mode(struct rtl8366_smi *smi, 1023 unsigned int mode) 1024{ 1025 u16 mask; 1026 u16 set; 1027 int err; 1028 1029 mode &= RTL8367_LED_CONFIG_DATA_M; 1030 1031 mask = (RTL8367_LED_CONFIG_DATA_M << RTL8367_LED_CONFIG_DATA_S) | 1032 RTL8367_LED_CONFIG_SEL; 1033 set = (mode << RTL8367_LED_CONFIG_DATA_S) | RTL8367_LED_CONFIG_SEL; 1034 1035 REG_RMW(smi, RTL8367_LED_CONFIG_REG, mask, set); 1036 1037 return 0; 1038} 1039 1040static int rtl8367_led_group_set_config(struct rtl8366_smi *smi, 1041 unsigned int led, unsigned int cfg) 1042{ 1043 u16 mask; 1044 u16 set; 1045 int err; 1046 1047 mask = (RTL8367_LED_CONFIG_LED_CFG_M << (led * 4)) | 1048 RTL8367_LED_CONFIG_SEL; 1049 set = (cfg & RTL8367_LED_CONFIG_LED_CFG_M) << (led * 4); 1050 1051 REG_RMW(smi, RTL8367_LED_CONFIG_REG, mask, set); 1052 return 0; 1053} 1054 1055static int rtl8367_led_op_select_parallel(struct rtl8366_smi *smi) 1056{ 1057 int err; 1058 1059 REG_WR(smi, RTL8367_LED_SYS_CONFIG_REG, 0x1472); 1060 return 0; 1061} 1062 1063static int rtl8367_led_blinkrate_set(struct rtl8366_smi *smi, unsigned int rate) 1064{ 1065 u16 mask; 1066 u16 set; 1067 int err; 1068 1069 mask = RTL8367_LED_MODE_RATE_M << RTL8367_LED_MODE_RATE_S; 1070 set = (rate & RTL8367_LED_MODE_RATE_M) << RTL8367_LED_MODE_RATE_S; 1071 REG_RMW(smi, RTL8367_LED_MODE_REG, mask, set); 1072 1073 return 0; 1074} 1075 1076#ifdef CONFIG_OF 1077static int rtl8367_extif_init_of(struct rtl8366_smi *smi, int id, 1078 const char *name) 1079{ 1080 struct rtl8367_extif_config *cfg; 1081 const __be32 *prop; 1082 int size; 1083 int err; 1084 1085 prop = of_get_property(smi->parent->of_node, name, &size); 1086 if (!prop) 1087 return rtl8367_extif_init(smi, id, NULL); 1088 1089 if (size != (9 * sizeof(*prop))) { 1090 dev_err(smi->parent, "%s property is invalid\n", name); 1091 return -EINVAL; 1092 } 1093 1094 cfg = kzalloc(sizeof(struct rtl8367_extif_config), GFP_KERNEL); 1095 if (!cfg) 1096 return -ENOMEM; 1097 1098 cfg->txdelay = be32_to_cpup(prop++); 1099 cfg->rxdelay = be32_to_cpup(prop++); 1100 cfg->mode = be32_to_cpup(prop++); 1101 cfg->ability.force_mode = be32_to_cpup(prop++); 1102 cfg->ability.txpause = be32_to_cpup(prop++); 1103 cfg->ability.rxpause = be32_to_cpup(prop++); 1104 cfg->ability.link = be32_to_cpup(prop++); 1105 cfg->ability.duplex = be32_to_cpup(prop++); 1106 cfg->ability.speed = be32_to_cpup(prop++); 1107 1108 err = rtl8367_extif_init(smi, id, cfg); 1109 kfree(cfg); 1110 1111 return err; 1112} 1113#else 1114static int rtl8367_extif_init_of(struct rtl8366_smi *smi, int id, 1115 const char *name) 1116{ 1117 return -EINVAL; 1118} 1119#endif 1120 1121static int rtl8367_setup(struct rtl8366_smi *smi) 1122{ 1123 struct rtl8367_platform_data *pdata; 1124 int err; 1125 int i; 1126 1127 pdata = smi->parent->platform_data; 1128 1129 err = rtl8367_init_regs(smi); 1130 if (err) 1131 return err; 1132 1133 /* initialize external interfaces */ 1134 if (smi->parent->of_node) { 1135 err = rtl8367_extif_init_of(smi, 0, "realtek,extif0"); 1136 if (err) 1137 return err; 1138 1139 err = rtl8367_extif_init_of(smi, 1, "realtek,extif1"); 1140 if (err) 1141 return err; 1142 } else { 1143 err = rtl8367_extif_init(smi, 0, pdata->extif0_cfg); 1144 if (err) 1145 return err; 1146 1147 err = rtl8367_extif_init(smi, 1, pdata->extif1_cfg); 1148 if (err) 1149 return err; 1150 } 1151 1152 /* set maximum packet length to 1536 bytes */ 1153 REG_RMW(smi, RTL8367_SWC0_REG, RTL8367_SWC0_MAX_LENGTH_MASK, 1154 RTL8367_SWC0_MAX_LENGTH_1536); 1155 1156 /* 1157 * discard VLAN tagged packets if the port is not a member of 1158 * the VLAN with which the packets is associated. 1159 */ 1160 REG_WR(smi, RTL8367_VLAN_INGRESS_REG, RTL8367_PORTS_ALL); 1161 1162 /* 1163 * Setup egress tag mode for each port. 1164 */ 1165 for (i = 0; i < RTL8367_NUM_PORTS; i++) 1166 REG_RMW(smi, 1167 RTL8367_PORT_CFG_REG(i), 1168 RTL8367_PORT_CFG_EGRESS_MODE_MASK << 1169 RTL8367_PORT_CFG_EGRESS_MODE_SHIFT, 1170 RTL8367_PORT_CFG_EGRESS_MODE_ORIGINAL << 1171 RTL8367_PORT_CFG_EGRESS_MODE_SHIFT); 1172 1173 /* setup LEDs */ 1174 err = rtl8367_led_group_set_ports(smi, 0, RTL8367_PORTS_ALL); 1175 if (err) 1176 return err; 1177 1178 err = rtl8367_led_group_set_mode(smi, 0); 1179 if (err) 1180 return err; 1181 1182 err = rtl8367_led_op_select_parallel(smi); 1183 if (err) 1184 return err; 1185 1186 err = rtl8367_led_blinkrate_set(smi, 1); 1187 if (err) 1188 return err; 1189 1190 err = rtl8367_led_group_set_config(smi, 0, 2); 1191 if (err) 1192 return err; 1193 1194 return 0; 1195} 1196 1197static int rtl8367_get_mib_counter(struct rtl8366_smi *smi, int counter, 1198 int port, unsigned long long *val) 1199{ 1200 struct rtl8366_mib_counter *mib; 1201 int offset; 1202 int i; 1203 int err; 1204 u32 addr, data; 1205 u64 mibvalue; 1206 1207 if (port > RTL8367_NUM_PORTS || counter >= RTL8367_MIB_COUNT) 1208 return -EINVAL; 1209 1210 mib = &rtl8367_mib_counters[counter]; 1211 addr = RTL8367_MIB_COUNTER_PORT_OFFSET * port + mib->offset; 1212 1213 /* 1214 * Writing access counter address first 1215 * then ASIC will prepare 64bits counter wait for being retrived 1216 */ 1217 REG_WR(smi, RTL8367_MIB_ADDRESS_REG, addr >> 2); 1218 1219 /* read MIB control register */ 1220 REG_RD(smi, RTL8367_MIB_CTRL_REG(0), &data); 1221 1222 if (data & RTL8367_MIB_CTRL_BUSY_MASK) 1223 return -EBUSY; 1224 1225 if (data & RTL8367_MIB_CTRL_RESET_MASK) 1226 return -EIO; 1227 1228 if (mib->length == 4) 1229 offset = 3; 1230 else 1231 offset = (mib->offset + 1) % 4; 1232 1233 mibvalue = 0; 1234 for (i = 0; i < mib->length; i++) { 1235 REG_RD(smi, RTL8367_MIB_COUNTER_REG(offset - i), &data); 1236 mibvalue = (mibvalue << 16) | (data & 0xFFFF); 1237 } 1238 1239 *val = mibvalue; 1240 return 0; 1241} 1242 1243static int rtl8367_get_vlan_4k(struct rtl8366_smi *smi, u32 vid, 1244 struct rtl8366_vlan_4k *vlan4k) 1245{ 1246 u32 data[RTL8367_TA_VLAN_DATA_SIZE]; 1247 int err; 1248 int i; 1249 1250 memset(vlan4k, '\0', sizeof(struct rtl8366_vlan_4k)); 1251 1252 if (vid >= RTL8367_NUM_VIDS) 1253 return -EINVAL; 1254 1255 /* write VID */ 1256 REG_WR(smi, RTL8367_TA_ADDR_REG, vid); 1257 1258 /* write table access control word */ 1259 REG_WR(smi, RTL8367_TA_CTRL_REG, RTL8367_TA_CTRL_CVLAN_READ); 1260 1261 for (i = 0; i < ARRAY_SIZE(data); i++) 1262 REG_RD(smi, RTL8367_TA_DATA_REG(i), &data[i]); 1263 1264 vlan4k->vid = vid; 1265 vlan4k->member = (data[0] >> RTL8367_TA_VLAN_MEMBER_SHIFT) & 1266 RTL8367_TA_VLAN_MEMBER_MASK; 1267 vlan4k->fid = (data[1] >> RTL8367_TA_VLAN_FID_SHIFT) & 1268 RTL8367_TA_VLAN_FID_MASK; 1269 vlan4k->untag = (data[2] >> RTL8367_TA_VLAN_UNTAG1_SHIFT) & 1270 RTL8367_TA_VLAN_UNTAG1_MASK; 1271 vlan4k->untag |= ((data[3] >> RTL8367_TA_VLAN_UNTAG2_SHIFT) & 1272 RTL8367_TA_VLAN_UNTAG2_MASK) << 2; 1273 1274 return 0; 1275} 1276 1277static int rtl8367_set_vlan_4k(struct rtl8366_smi *smi, 1278 const struct rtl8366_vlan_4k *vlan4k) 1279{ 1280 u32 data[RTL8367_TA_VLAN_DATA_SIZE]; 1281 int err; 1282 int i; 1283 1284 if (vlan4k->vid >= RTL8367_NUM_VIDS || 1285 vlan4k->member > RTL8367_TA_VLAN_MEMBER_MASK || 1286 vlan4k->untag > RTL8367_UNTAG_MASK || 1287 vlan4k->fid > RTL8367_FIDMAX) 1288 return -EINVAL; 1289 1290 data[0] = (vlan4k->member & RTL8367_TA_VLAN_MEMBER_MASK) << 1291 RTL8367_TA_VLAN_MEMBER_SHIFT; 1292 data[1] = (vlan4k->fid & RTL8367_TA_VLAN_FID_MASK) << 1293 RTL8367_TA_VLAN_FID_SHIFT; 1294 data[2] = (vlan4k->untag & RTL8367_TA_VLAN_UNTAG1_MASK) << 1295 RTL8367_TA_VLAN_UNTAG1_SHIFT; 1296 data[3] = ((vlan4k->untag >> 2) & RTL8367_TA_VLAN_UNTAG2_MASK) << 1297 RTL8367_TA_VLAN_UNTAG2_SHIFT; 1298 1299 for (i = 0; i < ARRAY_SIZE(data); i++) 1300 REG_WR(smi, RTL8367_TA_DATA_REG(i), data[i]); 1301 1302 /* write VID */ 1303 REG_WR(smi, RTL8367_TA_ADDR_REG, 1304 vlan4k->vid & RTL8367_TA_VLAN_VID_MASK); 1305 1306 /* write table access control word */ 1307 REG_WR(smi, RTL8367_TA_CTRL_REG, RTL8367_TA_CTRL_CVLAN_WRITE); 1308 1309 return 0; 1310} 1311 1312static int rtl8367_get_vlan_mc(struct rtl8366_smi *smi, u32 index, 1313 struct rtl8366_vlan_mc *vlanmc) 1314{ 1315 u32 data[RTL8367_VLAN_MC_DATA_SIZE]; 1316 int err; 1317 int i; 1318 1319 memset(vlanmc, '\0', sizeof(struct rtl8366_vlan_mc)); 1320 1321 if (index >= RTL8367_NUM_VLANS) 1322 return -EINVAL; 1323 1324 for (i = 0; i < ARRAY_SIZE(data); i++) 1325 REG_RD(smi, RTL8367_VLAN_MC_BASE(index) + i, &data[i]); 1326 1327 vlanmc->member = (data[0] >> RTL8367_VLAN_MC_MEMBER_SHIFT) & 1328 RTL8367_VLAN_MC_MEMBER_MASK; 1329 vlanmc->fid = (data[1] >> RTL8367_VLAN_MC_FID_SHIFT) & 1330 RTL8367_VLAN_MC_FID_MASK; 1331 vlanmc->vid = (data[3] >> RTL8367_VLAN_MC_EVID_SHIFT) & 1332 RTL8367_VLAN_MC_EVID_MASK; 1333 1334 return 0; 1335} 1336 1337static int rtl8367_set_vlan_mc(struct rtl8366_smi *smi, u32 index, 1338 const struct rtl8366_vlan_mc *vlanmc) 1339{ 1340 u32 data[RTL8367_VLAN_MC_DATA_SIZE]; 1341 int err; 1342 int i; 1343 1344 if (index >= RTL8367_NUM_VLANS || 1345 vlanmc->vid >= RTL8367_NUM_VIDS || 1346 vlanmc->priority > RTL8367_PRIORITYMAX || 1347 vlanmc->member > RTL8367_VLAN_MC_MEMBER_MASK || 1348 vlanmc->untag > RTL8367_UNTAG_MASK || 1349 vlanmc->fid > RTL8367_FIDMAX) 1350 return -EINVAL; 1351 1352 data[0] = (vlanmc->member & RTL8367_VLAN_MC_MEMBER_MASK) << 1353 RTL8367_VLAN_MC_MEMBER_SHIFT; 1354 data[1] = (vlanmc->fid & RTL8367_VLAN_MC_FID_MASK) << 1355 RTL8367_VLAN_MC_FID_SHIFT; 1356 data[2] = 0; 1357 data[3] = (vlanmc->vid & RTL8367_VLAN_MC_EVID_MASK) << 1358 RTL8367_VLAN_MC_EVID_SHIFT; 1359 1360 for (i = 0; i < ARRAY_SIZE(data); i++) 1361 REG_WR(smi, RTL8367_VLAN_MC_BASE(index) + i, data[i]); 1362 1363 return 0; 1364} 1365 1366static int rtl8367_get_mc_index(struct rtl8366_smi *smi, int port, int *val) 1367{ 1368 u32 data; 1369 int err; 1370 1371 if (port >= RTL8367_NUM_PORTS) 1372 return -EINVAL; 1373 1374 REG_RD(smi, RTL8367_VLAN_PVID_CTRL_REG(port), &data); 1375 1376 *val = (data >> RTL8367_VLAN_PVID_CTRL_SHIFT(port)) & 1377 RTL8367_VLAN_PVID_CTRL_MASK; 1378 1379 return 0; 1380} 1381 1382static int rtl8367_set_mc_index(struct rtl8366_smi *smi, int port, int index) 1383{ 1384 if (port >= RTL8367_NUM_PORTS || index >= RTL8367_NUM_VLANS) 1385 return -EINVAL; 1386 1387 return rtl8366_smi_rmwr(smi, RTL8367_VLAN_PVID_CTRL_REG(port), 1388 RTL8367_VLAN_PVID_CTRL_MASK << 1389 RTL8367_VLAN_PVID_CTRL_SHIFT(port), 1390 (index & RTL8367_VLAN_PVID_CTRL_MASK) << 1391 RTL8367_VLAN_PVID_CTRL_SHIFT(port)); 1392} 1393 1394static int rtl8367_enable_vlan(struct rtl8366_smi *smi, int enable) 1395{ 1396 return rtl8366_smi_rmwr(smi, RTL8367_VLAN_CTRL_REG, 1397 RTL8367_VLAN_CTRL_ENABLE, 1398 (enable) ? RTL8367_VLAN_CTRL_ENABLE : 0); 1399} 1400 1401static int rtl8367_enable_vlan4k(struct rtl8366_smi *smi, int enable) 1402{ 1403 return 0; 1404} 1405 1406static int rtl8367_is_vlan_valid(struct rtl8366_smi *smi, unsigned vlan) 1407{ 1408 unsigned max = RTL8367_NUM_VLANS; 1409 1410 if (smi->vlan4k_enabled) 1411 max = RTL8367_NUM_VIDS - 1; 1412 1413 if (vlan == 0 || vlan >= max) 1414 return 0; 1415 1416 return 1; 1417} 1418 1419static int rtl8367_enable_port(struct rtl8366_smi *smi, int port, int enable) 1420{ 1421 int err; 1422 1423 REG_WR(smi, RTL8367_PORT_ISOLATION_REG(port), 1424 (enable) ? RTL8367_PORTS_ALL : 0); 1425 1426 return 0; 1427} 1428 1429static int rtl8367_sw_reset_mibs(struct switch_dev *dev, 1430 const struct switch_attr *attr, 1431 struct switch_val *val) 1432{ 1433 struct rtl8366_smi *smi = sw_to_rtl8366_smi(dev); 1434 1435 return rtl8366_smi_rmwr(smi, RTL8367_MIB_CTRL_REG(0), 0, 1436 RTL8367_MIB_CTRL_GLOBAL_RESET_MASK); 1437} 1438 1439static int rtl8367_sw_get_port_link(struct switch_dev *dev, 1440 int port, 1441 struct switch_port_link *link) 1442{ 1443 struct rtl8366_smi *smi = sw_to_rtl8366_smi(dev); 1444 u32 data = 0; 1445 u32 speed; 1446 1447 if (port >= RTL8367_NUM_PORTS) 1448 return -EINVAL; 1449 1450 rtl8366_smi_read_reg(smi, RTL8367_PORT_STATUS_REG(port), &data); 1451 1452 link->link = !!(data & RTL8367_PORT_STATUS_LINK); 1453 if (!link->link) 1454 return 0; 1455 1456 link->duplex = !!(data & RTL8367_PORT_STATUS_DUPLEX); 1457 link->rx_flow = !!(data & RTL8367_PORT_STATUS_RXPAUSE); 1458 link->tx_flow = !!(data & RTL8367_PORT_STATUS_TXPAUSE); 1459 link->aneg = !!(data & RTL8367_PORT_STATUS_NWAY); 1460 1461 speed = (data & RTL8367_PORT_STATUS_SPEED_MASK); 1462 switch (speed) { 1463 case 0: 1464 link->speed = SWITCH_PORT_SPEED_10; 1465 break; 1466 case 1: 1467 link->speed = SWITCH_PORT_SPEED_100; 1468 break; 1469 case 2: 1470 link->speed = SWITCH_PORT_SPEED_1000; 1471 break; 1472 default: 1473 link->speed = SWITCH_PORT_SPEED_UNKNOWN; 1474 break; 1475 } 1476 1477 return 0; 1478} 1479 1480static int rtl8367_sw_get_max_length(struct switch_dev *dev, 1481 const struct switch_attr *attr, 1482 struct switch_val *val) 1483{ 1484 struct rtl8366_smi *smi = sw_to_rtl8366_smi(dev); 1485 u32 data; 1486 1487 rtl8366_smi_read_reg(smi, RTL8367_SWC0_REG, &data); 1488 val->value.i = (data & RTL8367_SWC0_MAX_LENGTH_MASK) >> 1489 RTL8367_SWC0_MAX_LENGTH_SHIFT; 1490 1491 return 0; 1492} 1493 1494static int rtl8367_sw_set_max_length(struct switch_dev *dev, 1495 const struct switch_attr *attr, 1496 struct switch_val *val) 1497{ 1498 struct rtl8366_smi *smi = sw_to_rtl8366_smi(dev); 1499 u32 max_len; 1500 1501 switch (val->value.i) { 1502 case 0: 1503 max_len = RTL8367_SWC0_MAX_LENGTH_1522; 1504 break; 1505 case 1: 1506 max_len = RTL8367_SWC0_MAX_LENGTH_1536; 1507 break; 1508 case 2: 1509 max_len = RTL8367_SWC0_MAX_LENGTH_1552; 1510 break; 1511 case 3: 1512 max_len = RTL8367_SWC0_MAX_LENGTH_16000; 1513 break; 1514 default: 1515 return -EINVAL; 1516 } 1517 1518 return rtl8366_smi_rmwr(smi, RTL8367_SWC0_REG, 1519 RTL8367_SWC0_MAX_LENGTH_MASK, max_len); 1520} 1521 1522 1523static int rtl8367_sw_reset_port_mibs(struct switch_dev *dev, 1524 const struct switch_attr *attr, 1525 struct switch_val *val) 1526{ 1527 struct rtl8366_smi *smi = sw_to_rtl8366_smi(dev); 1528 int port; 1529 1530 port = val->port_vlan; 1531 if (port >= RTL8367_NUM_PORTS) 1532 return -EINVAL; 1533 1534 return rtl8366_smi_rmwr(smi, RTL8367_MIB_CTRL_REG(port / 8), 0, 1535 RTL8367_MIB_CTRL_PORT_RESET_MASK(port % 8)); 1536} 1537 1538static struct switch_attr rtl8367_globals[] = { 1539 { 1540 .type = SWITCH_TYPE_INT, 1541 .name = "enable_vlan", 1542 .description = "Enable VLAN mode", 1543 .set = rtl8366_sw_set_vlan_enable, 1544 .get = rtl8366_sw_get_vlan_enable, 1545 .max = 1, 1546 .ofs = 1 1547 }, { 1548 .type = SWITCH_TYPE_INT, 1549 .name = "enable_vlan4k", 1550 .description = "Enable VLAN 4K mode", 1551 .set = rtl8366_sw_set_vlan_enable, 1552 .get = rtl8366_sw_get_vlan_enable, 1553 .max = 1, 1554 .ofs = 2 1555 }, { 1556 .type = SWITCH_TYPE_NOVAL, 1557 .name = "reset_mibs", 1558 .description = "Reset all MIB counters", 1559 .set = rtl8367_sw_reset_mibs, 1560 }, { 1561 .type = SWITCH_TYPE_INT, 1562 .name = "max_length", 1563 .description = "Get/Set the maximum length of valid packets" 1564 "(0:1522, 1:1536, 2:1552, 3:16000)", 1565 .set = rtl8367_sw_set_max_length, 1566 .get = rtl8367_sw_get_max_length, 1567 .max = 3, 1568 } 1569}; 1570 1571static struct switch_attr rtl8367_port[] = { 1572 { 1573 .type = SWITCH_TYPE_NOVAL, 1574 .name = "reset_mib", 1575 .description = "Reset single port MIB counters", 1576 .set = rtl8367_sw_reset_port_mibs, 1577 }, { 1578 .type = SWITCH_TYPE_STRING, 1579 .name = "mib", 1580 .description = "Get MIB counters for port", 1581 .max = 33, 1582 .set = NULL, 1583 .get = rtl8366_sw_get_port_mib, 1584 }, 1585}; 1586 1587static struct switch_attr rtl8367_vlan[] = { 1588 { 1589 .type = SWITCH_TYPE_STRING, 1590 .name = "info", 1591 .description = "Get vlan information", 1592 .max = 1, 1593 .set = NULL, 1594 .get = rtl8366_sw_get_vlan_info, 1595 }, { 1596 .type = SWITCH_TYPE_INT, 1597 .name = "fid", 1598 .description = "Get/Set vlan FID", 1599 .max = RTL8367_FIDMAX, 1600 .set = rtl8366_sw_set_vlan_fid, 1601 .get = rtl8366_sw_get_vlan_fid, 1602 }, 1603}; 1604 1605static const struct switch_dev_ops rtl8367_sw_ops = { 1606 .attr_global = { 1607 .attr = rtl8367_globals, 1608 .n_attr = ARRAY_SIZE(rtl8367_globals), 1609 }, 1610 .attr_port = { 1611 .attr = rtl8367_port, 1612 .n_attr = ARRAY_SIZE(rtl8367_port), 1613 }, 1614 .attr_vlan = { 1615 .attr = rtl8367_vlan, 1616 .n_attr = ARRAY_SIZE(rtl8367_vlan), 1617 }, 1618 1619 .get_vlan_ports = rtl8366_sw_get_vlan_ports, 1620 .set_vlan_ports = rtl8366_sw_set_vlan_ports, 1621 .get_port_pvid = rtl8366_sw_get_port_pvid, 1622 .set_port_pvid = rtl8366_sw_set_port_pvid, 1623 .reset_switch = rtl8366_sw_reset_switch, 1624 .get_port_link = rtl8367_sw_get_port_link, 1625}; 1626 1627static int rtl8367_switch_init(struct rtl8366_smi *smi) 1628{ 1629 struct switch_dev *dev = &smi->sw_dev; 1630 int err; 1631 1632 dev->name = "RTL8367"; 1633 dev->cpu_port = RTL8367_CPU_PORT_NUM; 1634 dev->ports = RTL8367_NUM_PORTS; 1635 dev->vlans = RTL8367_NUM_VIDS; 1636 dev->ops = &rtl8367_sw_ops; 1637 dev->alias = dev_name(smi->parent); 1638 1639 err = register_switch(dev, NULL); 1640 if (err) 1641 dev_err(smi->parent, "switch registration failed\n"); 1642 1643 return err; 1644} 1645 1646static void rtl8367_switch_cleanup(struct rtl8366_smi *smi) 1647{ 1648 unregister_switch(&smi->sw_dev); 1649} 1650 1651static int rtl8367_mii_read(struct mii_bus *bus, int addr, int reg) 1652{ 1653 struct rtl8366_smi *smi = bus->priv; 1654 u32 val = 0; 1655 int err; 1656 1657 err = rtl8367_read_phy_reg(smi, addr, reg, &val); 1658 if (err) 1659 return 0xffff; 1660 1661 return val; 1662} 1663 1664static int rtl8367_mii_write(struct mii_bus *bus, int addr, int reg, u16 val) 1665{ 1666 struct rtl8366_smi *smi = bus->priv; 1667 u32 t; 1668 int err; 1669 1670 err = rtl8367_write_phy_reg(smi, addr, reg, val); 1671 if (err) 1672 return err; 1673 1674 /* flush write */ 1675 (void) rtl8367_read_phy_reg(smi, addr, reg, &t); 1676 1677 return err; 1678} 1679 1680static int rtl8367_detect(struct rtl8366_smi *smi) 1681{ 1682 u32 rtl_no = 0; 1683 u32 rtl_ver = 0; 1684 char *chip_name; 1685 int ret; 1686 1687 ret = rtl8366_smi_read_reg(smi, RTL8367_RTL_NO_REG, &rtl_no); 1688 if (ret) { 1689 dev_err(smi->parent, "unable to read chip number\n"); 1690 return ret; 1691 } 1692 1693 switch (rtl_no) { 1694 case RTL8367_RTL_NO_8367R: 1695 chip_name = "8367R"; 1696 break; 1697 case RTL8367_RTL_NO_8367M: 1698 chip_name = "8367M"; 1699 break; 1700 default: 1701 dev_err(smi->parent, "unknown chip number (%04x)\n", rtl_no); 1702 return -ENODEV; 1703 } 1704 1705 ret = rtl8366_smi_read_reg(smi, RTL8367_RTL_VER_REG, &rtl_ver); 1706 if (ret) { 1707 dev_err(smi->parent, "unable to read chip version\n"); 1708 return ret; 1709 } 1710 1711 dev_info(smi->parent, "RTL%s ver. %u chip found\n", 1712 chip_name, rtl_ver & RTL8367_RTL_VER_MASK); 1713 1714 return 0; 1715} 1716 1717static struct rtl8366_smi_ops rtl8367_smi_ops = { 1718 .detect = rtl8367_detect, 1719 .reset_chip = rtl8367_reset_chip, 1720 .setup = rtl8367_setup, 1721 1722 .mii_read = rtl8367_mii_read, 1723 .mii_write = rtl8367_mii_write, 1724 1725 .get_vlan_mc = rtl8367_get_vlan_mc, 1726 .set_vlan_mc = rtl8367_set_vlan_mc, 1727 .get_vlan_4k = rtl8367_get_vlan_4k, 1728 .set_vlan_4k = rtl8367_set_vlan_4k, 1729 .get_mc_index = rtl8367_get_mc_index, 1730 .set_mc_index = rtl8367_set_mc_index, 1731 .get_mib_counter = rtl8367_get_mib_counter, 1732 .is_vlan_valid = rtl8367_is_vlan_valid, 1733 .enable_vlan = rtl8367_enable_vlan, 1734 .enable_vlan4k = rtl8367_enable_vlan4k, 1735 .enable_port = rtl8367_enable_port, 1736}; 1737 1738static int rtl8367_probe(struct platform_device *pdev) 1739{ 1740 struct rtl8366_smi *smi; 1741 int err; 1742 1743 smi = rtl8366_smi_probe(pdev); 1744 if (!smi) 1745 return -ENODEV; 1746 1747 smi->clk_delay = 1500; 1748 smi->cmd_read = 0xb9; 1749 smi->cmd_write = 0xb8; 1750 smi->ops = &rtl8367_smi_ops; 1751 smi->cpu_port = RTL8367_CPU_PORT_NUM; 1752 smi->num_ports = RTL8367_NUM_PORTS; 1753 smi->num_vlan_mc = RTL8367_NUM_VLANS; 1754 smi->mib_counters = rtl8367_mib_counters; 1755 smi->num_mib_counters = ARRAY_SIZE(rtl8367_mib_counters); 1756 1757 err = rtl8366_smi_init(smi); 1758 if (err) 1759 goto err_free_smi; 1760 1761 platform_set_drvdata(pdev, smi); 1762 1763 err = rtl8367_switch_init(smi); 1764 if (err) 1765 goto err_clear_drvdata; 1766 1767 return 0; 1768 1769 err_clear_drvdata: 1770 platform_set_drvdata(pdev, NULL); 1771 rtl8366_smi_cleanup(smi); 1772 err_free_smi: 1773 kfree(smi); 1774 return err; 1775} 1776 1777static int rtl8367_remove(struct platform_device *pdev) 1778{ 1779 struct rtl8366_smi *smi = platform_get_drvdata(pdev); 1780 1781 if (smi) { 1782 rtl8367_switch_cleanup(smi); 1783 platform_set_drvdata(pdev, NULL); 1784 rtl8366_smi_cleanup(smi); 1785 kfree(smi); 1786 } 1787 1788 return 0; 1789} 1790 1791static void rtl8367_shutdown(struct platform_device *pdev) 1792{ 1793 struct rtl8366_smi *smi = platform_get_drvdata(pdev); 1794 1795 if (smi) 1796 rtl8367_reset_chip(smi); 1797} 1798 1799#ifdef CONFIG_OF 1800static const struct of_device_id rtl8367_match[] = { 1801 { .compatible = "realtek,rtl8367" }, 1802 {}, 1803}; 1804MODULE_DEVICE_TABLE(of, rtl8367_match); 1805#endif 1806 1807static struct platform_driver rtl8367_driver = { 1808 .driver = { 1809 .name = RTL8367_DRIVER_NAME, 1810 .owner = THIS_MODULE, 1811#ifdef CONFIG_OF 1812 .of_match_table = of_match_ptr(rtl8367_match), 1813#endif 1814 }, 1815 .probe = rtl8367_probe, 1816 .remove = rtl8367_remove, 1817 .shutdown = rtl8367_shutdown, 1818}; 1819 1820static int __init rtl8367_module_init(void) 1821{ 1822 return platform_driver_register(&rtl8367_driver); 1823} 1824module_init(rtl8367_module_init); 1825 1826static void __exit rtl8367_module_exit(void) 1827{ 1828 platform_driver_unregister(&rtl8367_driver); 1829} 1830module_exit(rtl8367_module_exit); 1831 1832MODULE_DESCRIPTION(RTL8367_DRIVER_DESC); 1833MODULE_AUTHOR("Gabor Juhos <juhosg@openwrt.org>"); 1834MODULE_LICENSE("GPL v2"); 1835MODULE_ALIAS("platform:" RTL8367_DRIVER_NAME); 1836