generic: rtl836x: fix compiler warnings
[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 static int rtl8367_setup(struct rtl8366_smi *smi)
1077 {
1078         struct rtl8367_platform_data *pdata;
1079         int err;
1080         int i;
1081
1082         pdata = smi->parent->platform_data;
1083
1084         err = rtl8367_init_regs(smi);
1085         if (err)
1086                 return err;
1087
1088         /* initialize external interfaces */
1089         err = rtl8367_extif_init(smi, 0, pdata->extif0_cfg);
1090         if (err)
1091                 return err;
1092
1093         err = rtl8367_extif_init(smi, 1, pdata->extif1_cfg);
1094         if (err)
1095                 return err;
1096
1097         /* set maximum packet length to 1536 bytes */
1098         REG_RMW(smi, RTL8367_SWC0_REG, RTL8367_SWC0_MAX_LENGTH_MASK,
1099                 RTL8367_SWC0_MAX_LENGTH_1536);
1100
1101         /*
1102          * discard VLAN tagged packets if the port is not a member of
1103          * the VLAN with which the packets is associated.
1104          */
1105         REG_WR(smi, RTL8367_VLAN_INGRESS_REG, RTL8367_PORTS_ALL);
1106
1107         /*
1108          * Setup egress tag mode for each port.
1109          */
1110         for (i = 0; i < RTL8367_NUM_PORTS; i++)
1111                 REG_RMW(smi,
1112                         RTL8367_PORT_CFG_REG(i),
1113                         RTL8367_PORT_CFG_EGRESS_MODE_MASK <<
1114                                 RTL8367_PORT_CFG_EGRESS_MODE_SHIFT,
1115                         RTL8367_PORT_CFG_EGRESS_MODE_ORIGINAL <<
1116                                 RTL8367_PORT_CFG_EGRESS_MODE_SHIFT);
1117
1118         /* setup LEDs */
1119         err = rtl8367_led_group_set_ports(smi, 0, RTL8367_PORTS_ALL);
1120         if (err)
1121                 return err;
1122
1123         err = rtl8367_led_group_set_mode(smi, 0);
1124         if (err)
1125                 return err;
1126
1127         err = rtl8367_led_op_select_parallel(smi);
1128         if (err)
1129                 return err;
1130
1131         err = rtl8367_led_blinkrate_set(smi, 1);
1132         if (err)
1133                 return err;
1134
1135         err = rtl8367_led_group_set_config(smi, 0, 2);
1136         if (err)
1137                 return err;
1138
1139         return 0;
1140 }
1141
1142 static int rtl8367_get_mib_counter(struct rtl8366_smi *smi, int counter,
1143                                    int port, unsigned long long *val)
1144 {
1145         struct rtl8366_mib_counter *mib;
1146         int offset;
1147         int i;
1148         int err;
1149         u32 addr, data;
1150         u64 mibvalue;
1151
1152         if (port > RTL8367_NUM_PORTS || counter >= RTL8367_MIB_COUNT)
1153                 return -EINVAL;
1154
1155         mib = &rtl8367_mib_counters[counter];
1156         addr = RTL8367_MIB_COUNTER_PORT_OFFSET * port + mib->offset;
1157
1158         /*
1159          * Writing access counter address first
1160          * then ASIC will prepare 64bits counter wait for being retrived
1161          */
1162         REG_WR(smi, RTL8367_MIB_ADDRESS_REG, addr >> 2);
1163
1164         /* read MIB control register */
1165         REG_RD(smi, RTL8367_MIB_CTRL_REG(0), &data);
1166
1167         if (data & RTL8367_MIB_CTRL_BUSY_MASK)
1168                 return -EBUSY;
1169
1170         if (data & RTL8367_MIB_CTRL_RESET_MASK)
1171                 return -EIO;
1172
1173         if (mib->length == 4)
1174                 offset = 3;
1175         else
1176                 offset = (mib->offset + 1) % 4;
1177
1178         mibvalue = 0;
1179         for (i = 0; i < mib->length; i++) {
1180                 REG_RD(smi, RTL8367_MIB_COUNTER_REG(offset - i), &data);
1181                 mibvalue = (mibvalue << 16) | (data & 0xFFFF);
1182         }
1183
1184         *val = mibvalue;
1185         return 0;
1186 }
1187
1188 static int rtl8367_get_vlan_4k(struct rtl8366_smi *smi, u32 vid,
1189                                 struct rtl8366_vlan_4k *vlan4k)
1190 {
1191         u32 data[RTL8367_TA_VLAN_DATA_SIZE];
1192         int err;
1193         int i;
1194
1195         memset(vlan4k, '\0', sizeof(struct rtl8366_vlan_4k));
1196
1197         if (vid >= RTL8367_NUM_VIDS)
1198                 return -EINVAL;
1199
1200         /* write VID */
1201         REG_WR(smi, RTL8367_TA_ADDR_REG, vid);
1202
1203         /* write table access control word */
1204         REG_WR(smi, RTL8367_TA_CTRL_REG, RTL8367_TA_CTRL_CVLAN_READ);
1205
1206         for (i = 0; i < ARRAY_SIZE(data); i++)
1207                 REG_RD(smi, RTL8367_TA_DATA_REG(i), &data[i]);
1208
1209         vlan4k->vid = vid;
1210         vlan4k->member = (data[0] >> RTL8367_TA_VLAN_MEMBER_SHIFT) &
1211                          RTL8367_TA_VLAN_MEMBER_MASK;
1212         vlan4k->fid = (data[1] >> RTL8367_TA_VLAN_FID_SHIFT) &
1213                       RTL8367_TA_VLAN_FID_MASK;
1214         vlan4k->untag = (data[2] >> RTL8367_TA_VLAN_UNTAG1_SHIFT) &
1215                         RTL8367_TA_VLAN_UNTAG1_MASK;
1216         vlan4k->untag |= ((data[3] >> RTL8367_TA_VLAN_UNTAG2_SHIFT) &
1217                           RTL8367_TA_VLAN_UNTAG2_MASK) << 2;
1218
1219         return 0;
1220 }
1221
1222 static int rtl8367_set_vlan_4k(struct rtl8366_smi *smi,
1223                                 const struct rtl8366_vlan_4k *vlan4k)
1224 {
1225         u32 data[RTL8367_TA_VLAN_DATA_SIZE];
1226         int err;
1227         int i;
1228
1229         if (vlan4k->vid >= RTL8367_NUM_VIDS ||
1230             vlan4k->member > RTL8367_TA_VLAN_MEMBER_MASK ||
1231             vlan4k->untag > RTL8367_UNTAG_MASK ||
1232             vlan4k->fid > RTL8367_FIDMAX)
1233                 return -EINVAL;
1234
1235         data[0] = (vlan4k->member & RTL8367_TA_VLAN_MEMBER_MASK) <<
1236                   RTL8367_TA_VLAN_MEMBER_SHIFT;
1237         data[1] = (vlan4k->fid & RTL8367_TA_VLAN_FID_MASK) <<
1238                   RTL8367_TA_VLAN_FID_SHIFT;
1239         data[2] = (vlan4k->untag & RTL8367_TA_VLAN_UNTAG1_MASK) <<
1240                   RTL8367_TA_VLAN_UNTAG1_SHIFT;
1241         data[3] = ((vlan4k->untag >> 2) & RTL8367_TA_VLAN_UNTAG2_MASK) <<
1242                   RTL8367_TA_VLAN_UNTAG2_SHIFT;
1243
1244         for (i = 0; i < ARRAY_SIZE(data); i++)
1245                 REG_WR(smi, RTL8367_TA_DATA_REG(i), data[i]);
1246
1247         /* write VID */
1248         REG_WR(smi, RTL8367_TA_ADDR_REG,
1249                vlan4k->vid & RTL8367_TA_VLAN_VID_MASK);
1250
1251         /* write table access control word */
1252         REG_WR(smi, RTL8367_TA_CTRL_REG, RTL8367_TA_CTRL_CVLAN_WRITE);
1253
1254         return 0;
1255 }
1256
1257 static int rtl8367_get_vlan_mc(struct rtl8366_smi *smi, u32 index,
1258                                 struct rtl8366_vlan_mc *vlanmc)
1259 {
1260         u32 data[RTL8367_VLAN_MC_DATA_SIZE];
1261         int err;
1262         int i;
1263
1264         memset(vlanmc, '\0', sizeof(struct rtl8366_vlan_mc));
1265
1266         if (index >= RTL8367_NUM_VLANS)
1267                 return -EINVAL;
1268
1269         for (i = 0; i < ARRAY_SIZE(data); i++)
1270                 REG_RD(smi, RTL8367_VLAN_MC_BASE(index) + i, &data[i]);
1271
1272         vlanmc->member = (data[0] >> RTL8367_VLAN_MC_MEMBER_SHIFT) &
1273                          RTL8367_VLAN_MC_MEMBER_MASK;
1274         vlanmc->fid = (data[1] >> RTL8367_VLAN_MC_FID_SHIFT) &
1275                       RTL8367_VLAN_MC_FID_MASK;
1276         vlanmc->vid = (data[3] >> RTL8367_VLAN_MC_EVID_SHIFT) &
1277                       RTL8367_VLAN_MC_EVID_MASK;
1278
1279         return 0;
1280 }
1281
1282 static int rtl8367_set_vlan_mc(struct rtl8366_smi *smi, u32 index,
1283                                 const struct rtl8366_vlan_mc *vlanmc)
1284 {
1285         u32 data[RTL8367_VLAN_MC_DATA_SIZE];
1286         int err;
1287         int i;
1288
1289         if (index >= RTL8367_NUM_VLANS ||
1290             vlanmc->vid >= RTL8367_NUM_VIDS ||
1291             vlanmc->priority > RTL8367_PRIORITYMAX ||
1292             vlanmc->member > RTL8367_VLAN_MC_MEMBER_MASK ||
1293             vlanmc->untag > RTL8367_UNTAG_MASK ||
1294             vlanmc->fid > RTL8367_FIDMAX)
1295                 return -EINVAL;
1296
1297         data[0] = (vlanmc->member & RTL8367_VLAN_MC_MEMBER_MASK) <<
1298                   RTL8367_VLAN_MC_MEMBER_SHIFT;
1299         data[1] = (vlanmc->fid & RTL8367_VLAN_MC_FID_MASK) <<
1300                   RTL8367_VLAN_MC_FID_SHIFT;
1301         data[2] = 0;
1302         data[3] = (vlanmc->vid & RTL8367_VLAN_MC_EVID_MASK) <<
1303                    RTL8367_VLAN_MC_EVID_SHIFT;
1304
1305         for (i = 0; i < ARRAY_SIZE(data); i++)
1306                 REG_WR(smi, RTL8367_VLAN_MC_BASE(index) + i, data[i]);
1307
1308         return 0;
1309 }
1310
1311 static int rtl8367_get_mc_index(struct rtl8366_smi *smi, int port, int *val)
1312 {
1313         u32 data;
1314         int err;
1315
1316         if (port >= RTL8367_NUM_PORTS)
1317                 return -EINVAL;
1318
1319         REG_RD(smi, RTL8367_VLAN_PVID_CTRL_REG(port), &data);
1320
1321         *val = (data >> RTL8367_VLAN_PVID_CTRL_SHIFT(port)) &
1322                RTL8367_VLAN_PVID_CTRL_MASK;
1323
1324         return 0;
1325 }
1326
1327 static int rtl8367_set_mc_index(struct rtl8366_smi *smi, int port, int index)
1328 {
1329         if (port >= RTL8367_NUM_PORTS || index >= RTL8367_NUM_VLANS)
1330                 return -EINVAL;
1331
1332         return rtl8366_smi_rmwr(smi, RTL8367_VLAN_PVID_CTRL_REG(port),
1333                                 RTL8367_VLAN_PVID_CTRL_MASK <<
1334                                         RTL8367_VLAN_PVID_CTRL_SHIFT(port),
1335                                 (index & RTL8367_VLAN_PVID_CTRL_MASK) <<
1336                                         RTL8367_VLAN_PVID_CTRL_SHIFT(port));
1337 }
1338
1339 static int rtl8367_enable_vlan(struct rtl8366_smi *smi, int enable)
1340 {
1341         return rtl8366_smi_rmwr(smi, RTL8367_VLAN_CTRL_REG,
1342                                 RTL8367_VLAN_CTRL_ENABLE,
1343                                 (enable) ? RTL8367_VLAN_CTRL_ENABLE : 0);
1344 }
1345
1346 static int rtl8367_enable_vlan4k(struct rtl8366_smi *smi, int enable)
1347 {
1348         return 0;
1349 }
1350
1351 static int rtl8367_is_vlan_valid(struct rtl8366_smi *smi, unsigned vlan)
1352 {
1353         unsigned max = RTL8367_NUM_VLANS;
1354
1355         if (smi->vlan4k_enabled)
1356                 max = RTL8367_NUM_VIDS - 1;
1357
1358         if (vlan == 0 || vlan >= max)
1359                 return 0;
1360
1361         return 1;
1362 }
1363
1364 static int rtl8367_enable_port(struct rtl8366_smi *smi, int port, int enable)
1365 {
1366         int err;
1367
1368         REG_WR(smi, RTL8367_PORT_ISOLATION_REG(port),
1369                (enable) ? RTL8367_PORTS_ALL : 0);
1370
1371         return 0;
1372 }
1373
1374 static int rtl8367_sw_reset_mibs(struct switch_dev *dev,
1375                                   const struct switch_attr *attr,
1376                                   struct switch_val *val)
1377 {
1378         struct rtl8366_smi *smi = sw_to_rtl8366_smi(dev);
1379
1380         return rtl8366_smi_rmwr(smi, RTL8367_MIB_CTRL_REG(0), 0,
1381                                 RTL8367_MIB_CTRL_GLOBAL_RESET_MASK);
1382 }
1383
1384 static int rtl8367_sw_get_port_link(struct switch_dev *dev,
1385                                     int port,
1386                                     struct switch_port_link *link)
1387 {
1388         struct rtl8366_smi *smi = sw_to_rtl8366_smi(dev);
1389         u32 data = 0;
1390         u32 speed;
1391
1392         if (port >= RTL8367_NUM_PORTS)
1393                 return -EINVAL;
1394
1395         rtl8366_smi_read_reg(smi, RTL8367_PORT_STATUS_REG(port), &data);
1396
1397         link->link = !!(data & RTL8367_PORT_STATUS_LINK);
1398         if (!link->link)
1399                 return 0;
1400
1401         link->duplex = !!(data & RTL8367_PORT_STATUS_DUPLEX);
1402         link->rx_flow = !!(data & RTL8367_PORT_STATUS_RXPAUSE);
1403         link->tx_flow = !!(data & RTL8367_PORT_STATUS_TXPAUSE);
1404         link->aneg = !!(data & RTL8367_PORT_STATUS_NWAY);
1405
1406         speed = (data & RTL8367_PORT_STATUS_SPEED_MASK);
1407         switch (speed) {
1408         case 0:
1409                 link->speed = SWITCH_PORT_SPEED_10;
1410                 break;
1411         case 1:
1412                 link->speed = SWITCH_PORT_SPEED_100;
1413                 break;
1414         case 2:
1415                 link->speed = SWITCH_PORT_SPEED_1000;
1416                 break;
1417         default:
1418                 link->speed = SWITCH_PORT_SPEED_UNKNOWN;
1419                 break;
1420         }
1421
1422         return 0;
1423 }
1424
1425 static int rtl8367_sw_get_max_length(struct switch_dev *dev,
1426                                      const struct switch_attr *attr,
1427                                      struct switch_val *val)
1428 {
1429         struct rtl8366_smi *smi = sw_to_rtl8366_smi(dev);
1430         u32 data;
1431
1432         rtl8366_smi_read_reg(smi, RTL8367_SWC0_REG, &data);
1433         val->value.i = (data & RTL8367_SWC0_MAX_LENGTH_MASK) >>
1434                         RTL8367_SWC0_MAX_LENGTH_SHIFT;
1435
1436         return 0;
1437 }
1438
1439 static int rtl8367_sw_set_max_length(struct switch_dev *dev,
1440                                      const struct switch_attr *attr,
1441                                      struct switch_val *val)
1442 {
1443         struct rtl8366_smi *smi = sw_to_rtl8366_smi(dev);
1444         u32 max_len;
1445
1446         switch (val->value.i) {
1447         case 0:
1448                 max_len = RTL8367_SWC0_MAX_LENGTH_1522;
1449                 break;
1450         case 1:
1451                 max_len = RTL8367_SWC0_MAX_LENGTH_1536;
1452                 break;
1453         case 2:
1454                 max_len = RTL8367_SWC0_MAX_LENGTH_1552;
1455                 break;
1456         case 3:
1457                 max_len = RTL8367_SWC0_MAX_LENGTH_16000;
1458                 break;
1459         default:
1460                 return -EINVAL;
1461         }
1462
1463         return rtl8366_smi_rmwr(smi, RTL8367_SWC0_REG,
1464                                 RTL8367_SWC0_MAX_LENGTH_MASK, max_len);
1465 }
1466
1467
1468 static int rtl8367_sw_reset_port_mibs(struct switch_dev *dev,
1469                                        const struct switch_attr *attr,
1470                                        struct switch_val *val)
1471 {
1472         struct rtl8366_smi *smi = sw_to_rtl8366_smi(dev);
1473         int port;
1474
1475         port = val->port_vlan;
1476         if (port >= RTL8367_NUM_PORTS)
1477                 return -EINVAL;
1478
1479         return rtl8366_smi_rmwr(smi, RTL8367_MIB_CTRL_REG(port / 8), 0,
1480                                 RTL8367_MIB_CTRL_PORT_RESET_MASK(port % 8));
1481 }
1482
1483 static struct switch_attr rtl8367_globals[] = {
1484         {
1485                 .type = SWITCH_TYPE_INT,
1486                 .name = "enable_vlan",
1487                 .description = "Enable VLAN mode",
1488                 .set = rtl8366_sw_set_vlan_enable,
1489                 .get = rtl8366_sw_get_vlan_enable,
1490                 .max = 1,
1491                 .ofs = 1
1492         }, {
1493                 .type = SWITCH_TYPE_INT,
1494                 .name = "enable_vlan4k",
1495                 .description = "Enable VLAN 4K mode",
1496                 .set = rtl8366_sw_set_vlan_enable,
1497                 .get = rtl8366_sw_get_vlan_enable,
1498                 .max = 1,
1499                 .ofs = 2
1500         }, {
1501                 .type = SWITCH_TYPE_NOVAL,
1502                 .name = "reset_mibs",
1503                 .description = "Reset all MIB counters",
1504                 .set = rtl8367_sw_reset_mibs,
1505         }, {
1506                 .type = SWITCH_TYPE_INT,
1507                 .name = "max_length",
1508                 .description = "Get/Set the maximum length of valid packets"
1509                                "(0:1522, 1:1536, 2:1552, 3:16000)",
1510                 .set = rtl8367_sw_set_max_length,
1511                 .get = rtl8367_sw_get_max_length,
1512                 .max = 3,
1513         }
1514 };
1515
1516 static struct switch_attr rtl8367_port[] = {
1517         {
1518                 .type = SWITCH_TYPE_NOVAL,
1519                 .name = "reset_mib",
1520                 .description = "Reset single port MIB counters",
1521                 .set = rtl8367_sw_reset_port_mibs,
1522         }, {
1523                 .type = SWITCH_TYPE_STRING,
1524                 .name = "mib",
1525                 .description = "Get MIB counters for port",
1526                 .max = 33,
1527                 .set = NULL,
1528                 .get = rtl8366_sw_get_port_mib,
1529         },
1530 };
1531
1532 static struct switch_attr rtl8367_vlan[] = {
1533         {
1534                 .type = SWITCH_TYPE_STRING,
1535                 .name = "info",
1536                 .description = "Get vlan information",
1537                 .max = 1,
1538                 .set = NULL,
1539                 .get = rtl8366_sw_get_vlan_info,
1540         },
1541 };
1542
1543 static const struct switch_dev_ops rtl8367_sw_ops = {
1544         .attr_global = {
1545                 .attr = rtl8367_globals,
1546                 .n_attr = ARRAY_SIZE(rtl8367_globals),
1547         },
1548         .attr_port = {
1549                 .attr = rtl8367_port,
1550                 .n_attr = ARRAY_SIZE(rtl8367_port),
1551         },
1552         .attr_vlan = {
1553                 .attr = rtl8367_vlan,
1554                 .n_attr = ARRAY_SIZE(rtl8367_vlan),
1555         },
1556
1557         .get_vlan_ports = rtl8366_sw_get_vlan_ports,
1558         .set_vlan_ports = rtl8366_sw_set_vlan_ports,
1559         .get_port_pvid = rtl8366_sw_get_port_pvid,
1560         .set_port_pvid = rtl8366_sw_set_port_pvid,
1561         .reset_switch = rtl8366_sw_reset_switch,
1562         .get_port_link = rtl8367_sw_get_port_link,
1563 };
1564
1565 static int rtl8367_switch_init(struct rtl8366_smi *smi)
1566 {
1567         struct switch_dev *dev = &smi->sw_dev;
1568         int err;
1569
1570         dev->name = "RTL8367";
1571         dev->cpu_port = RTL8367_CPU_PORT_NUM;
1572         dev->ports = RTL8367_NUM_PORTS;
1573         dev->vlans = RTL8367_NUM_VIDS;
1574         dev->ops = &rtl8367_sw_ops;
1575         dev->alias = dev_name(smi->parent);
1576
1577         err = register_switch(dev, NULL);
1578         if (err)
1579                 dev_err(smi->parent, "switch registration failed\n");
1580
1581         return err;
1582 }
1583
1584 static void rtl8367_switch_cleanup(struct rtl8366_smi *smi)
1585 {
1586         unregister_switch(&smi->sw_dev);
1587 }
1588
1589 static int rtl8367_mii_read(struct mii_bus *bus, int addr, int reg)
1590 {
1591         struct rtl8366_smi *smi = bus->priv;
1592         u32 val = 0;
1593         int err;
1594
1595         err = rtl8367_read_phy_reg(smi, addr, reg, &val);
1596         if (err)
1597                 return 0xffff;
1598
1599         return val;
1600 }
1601
1602 static int rtl8367_mii_write(struct mii_bus *bus, int addr, int reg, u16 val)
1603 {
1604         struct rtl8366_smi *smi = bus->priv;
1605         u32 t;
1606         int err;
1607
1608         err = rtl8367_write_phy_reg(smi, addr, reg, val);
1609         if (err)
1610                 return err;
1611
1612         /* flush write */
1613         (void) rtl8367_read_phy_reg(smi, addr, reg, &t);
1614
1615         return err;
1616 }
1617
1618 static int rtl8367_detect(struct rtl8366_smi *smi)
1619 {
1620         u32 rtl_no = 0;
1621         u32 rtl_ver = 0;
1622         char *chip_name;
1623         int ret;
1624
1625         ret = rtl8366_smi_read_reg(smi, RTL8367_RTL_NO_REG, &rtl_no);
1626         if (ret) {
1627                 dev_err(smi->parent, "unable to read chip number\n");
1628                 return ret;
1629         }
1630
1631         switch (rtl_no) {
1632         case RTL8367_RTL_NO_8367R:
1633                 chip_name = "8367R";
1634                 break;
1635         case RTL8367_RTL_NO_8367M:
1636                 chip_name = "8367M";
1637                 break;
1638         default:
1639                 dev_err(smi->parent, "unknown chip number (%04x)\n", rtl_no);
1640                 return -ENODEV;
1641         }
1642
1643         ret = rtl8366_smi_read_reg(smi, RTL8367_RTL_VER_REG, &rtl_ver);
1644         if (ret) {
1645                 dev_err(smi->parent, "unable to read chip version\n");
1646                 return ret;
1647         }
1648
1649         dev_info(smi->parent, "RTL%s ver. %u chip found\n",
1650                  chip_name, rtl_ver & RTL8367_RTL_VER_MASK);
1651
1652         return 0;
1653 }
1654
1655 static struct rtl8366_smi_ops rtl8367_smi_ops = {
1656         .detect         = rtl8367_detect,
1657         .reset_chip     = rtl8367_reset_chip,
1658         .setup          = rtl8367_setup,
1659
1660         .mii_read       = rtl8367_mii_read,
1661         .mii_write      = rtl8367_mii_write,
1662
1663         .get_vlan_mc    = rtl8367_get_vlan_mc,
1664         .set_vlan_mc    = rtl8367_set_vlan_mc,
1665         .get_vlan_4k    = rtl8367_get_vlan_4k,
1666         .set_vlan_4k    = rtl8367_set_vlan_4k,
1667         .get_mc_index   = rtl8367_get_mc_index,
1668         .set_mc_index   = rtl8367_set_mc_index,
1669         .get_mib_counter = rtl8367_get_mib_counter,
1670         .is_vlan_valid  = rtl8367_is_vlan_valid,
1671         .enable_vlan    = rtl8367_enable_vlan,
1672         .enable_vlan4k  = rtl8367_enable_vlan4k,
1673         .enable_port    = rtl8367_enable_port,
1674 };
1675
1676 static int __devinit rtl8367_probe(struct platform_device *pdev)
1677 {
1678         struct rtl8366_smi *smi;
1679         int err;
1680
1681         smi = rtl8366_smi_probe(pdev);
1682         if (!smi)
1683                 return -ENODEV;
1684
1685         smi->clk_delay = 1500;
1686         smi->cmd_read = 0xb9;
1687         smi->cmd_write = 0xb8;
1688         smi->ops = &rtl8367_smi_ops;
1689         smi->cpu_port = RTL8367_CPU_PORT_NUM;
1690         smi->num_ports = RTL8367_NUM_PORTS;
1691         smi->num_vlan_mc = RTL8367_NUM_VLANS;
1692         smi->mib_counters = rtl8367_mib_counters;
1693         smi->num_mib_counters = ARRAY_SIZE(rtl8367_mib_counters);
1694
1695         err = rtl8366_smi_init(smi);
1696         if (err)
1697                 goto err_free_smi;
1698
1699         platform_set_drvdata(pdev, smi);
1700
1701         err = rtl8367_switch_init(smi);
1702         if (err)
1703                 goto err_clear_drvdata;
1704
1705         return 0;
1706
1707  err_clear_drvdata:
1708         platform_set_drvdata(pdev, NULL);
1709         rtl8366_smi_cleanup(smi);
1710  err_free_smi:
1711         kfree(smi);
1712         return err;
1713 }
1714
1715 static int __devexit rtl8367_remove(struct platform_device *pdev)
1716 {
1717         struct rtl8366_smi *smi = platform_get_drvdata(pdev);
1718
1719         if (smi) {
1720                 rtl8367_switch_cleanup(smi);
1721                 platform_set_drvdata(pdev, NULL);
1722                 rtl8366_smi_cleanup(smi);
1723                 kfree(smi);
1724         }
1725
1726         return 0;
1727 }
1728
1729 static void rtl8367_shutdown(struct platform_device *pdev)
1730 {
1731         struct rtl8366_smi *smi = platform_get_drvdata(pdev);
1732
1733         if (smi)
1734                 rtl8367_reset_chip(smi);
1735 }
1736
1737 #ifdef CONFIG_OF
1738 static const struct of_device_id rtl8367_match[] = {
1739        { .compatible = "rtl8367" },
1740        {},
1741 };
1742 MODULE_DEVICE_TABLE(of, rtl83767_match);
1743 #endif
1744
1745 static struct platform_driver rtl8367_driver = {
1746         .driver = {
1747                 .name           = RTL8367_DRIVER_NAME,
1748                 .owner          = THIS_MODULE,
1749 #ifdef CONFIG_OF
1750                 .of_match_table = of_match_ptr(rtl8367_match),
1751 #endif
1752         },
1753         .probe          = rtl8367_probe,
1754         .remove         = __devexit_p(rtl8367_remove),
1755         .shutdown       = rtl8367_shutdown,
1756 };
1757
1758 static int __init rtl8367_module_init(void)
1759 {
1760         return platform_driver_register(&rtl8367_driver);
1761 }
1762 module_init(rtl8367_module_init);
1763
1764 static void __exit rtl8367_module_exit(void)
1765 {
1766         platform_driver_unregister(&rtl8367_driver);
1767 }
1768 module_exit(rtl8367_module_exit);
1769
1770 MODULE_DESCRIPTION(RTL8367_DRIVER_DESC);
1771 MODULE_AUTHOR("Gabor Juhos <juhosg@openwrt.org>");
1772 MODULE_LICENSE("GPL v2");
1773 MODULE_ALIAS("platform:" RTL8367_DRIVER_NAME);