Merge pull request #580 from wigyori/cc-libpcap
[15.05/openwrt.git] / target / linux / generic / files / drivers / net / phy / rtl8367.c
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
251 struct rtl8367_initval {
252         u16 reg;
253         u16 val;
254 };
255
256 static 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
319 static 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
362 static 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
405 static 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
464 static 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
516 static 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
570 static 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
617 static 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
630 static 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
677 static 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
725 static 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
757 static 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
782 static 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
807 static 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
861 static 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
886 static 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
933 static 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
961 static 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
980 static 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
1006 static 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
1022 static 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
1040 static 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
1055 static 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
1063 static 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
1077 static 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
1114 static int rtl8367_extif_init_of(struct rtl8366_smi *smi, int id,
1115                                  const char *name)
1116 {
1117         return -EINVAL;
1118 }
1119 #endif
1120
1121 static 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
1197 static 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
1243 static 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
1277 static 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
1312 static 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
1337 static 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
1366 static 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
1382 static 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
1394 static 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
1401 static int rtl8367_enable_vlan4k(struct rtl8366_smi *smi, int enable)
1402 {
1403         return 0;
1404 }
1405
1406 static 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
1419 static 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
1429 static 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
1439 static 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
1480 static 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
1494 static 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
1523 static 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
1538 static 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
1571 static 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
1587 static 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
1605 static 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
1627 static 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
1646 static void rtl8367_switch_cleanup(struct rtl8366_smi *smi)
1647 {
1648         unregister_switch(&smi->sw_dev);
1649 }
1650
1651 static 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
1664 static 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
1680 static 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
1717 static 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
1738 static 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
1777 static 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
1791 static 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
1800 static const struct of_device_id rtl8367_match[] = {
1801        { .compatible = "realtek,rtl8367" },
1802        {},
1803 };
1804 MODULE_DEVICE_TABLE(of, rtl8367_match);
1805 #endif
1806
1807 static 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
1820 static int __init rtl8367_module_init(void)
1821 {
1822         return platform_driver_register(&rtl8367_driver);
1823 }
1824 module_init(rtl8367_module_init);
1825
1826 static void __exit rtl8367_module_exit(void)
1827 {
1828         platform_driver_unregister(&rtl8367_driver);
1829 }
1830 module_exit(rtl8367_module_exit);
1831
1832 MODULE_DESCRIPTION(RTL8367_DRIVER_DESC);
1833 MODULE_AUTHOR("Gabor Juhos <juhosg@openwrt.org>");
1834 MODULE_LICENSE("GPL v2");
1835 MODULE_ALIAS("platform:" RTL8367_DRIVER_NAME);