blob: 09a748327fc6422d442b8a8baf8ceef56fc58d9e [file] [log] [blame]
Juergen Beiserta1292592017-04-18 10:48:25 +02001/*
2 * Copyright (C) 2017 Pengutronix, Juergen Borleis <kernel@pengutronix.de>
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * version 2, as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 */
14#include <linux/kernel.h>
15#include <linux/module.h>
16#include <linux/gpio/consumer.h>
17#include <linux/regmap.h>
18#include <linux/mutex.h>
19#include <linux/mii.h>
Egil Hjelmeland4d6a78b2017-09-19 10:09:24 +020020#include <linux/phy.h>
Egil Hjelmelandd99a86a2017-10-10 14:49:53 +020021#include <linux/if_bridge.h>
Juergen Beiserta1292592017-04-18 10:48:25 +020022
23#include "lan9303.h"
24
Egil Hjelmelanda368ca52017-08-05 13:05:47 +020025#define LAN9303_NUM_PORTS 3
26
Egil Hjelmelandab78acb2017-07-30 19:58:54 +020027/* 13.2 System Control and Status Registers
28 * Multiply register number by 4 to get address offset.
29 */
Juergen Beiserta1292592017-04-18 10:48:25 +020030#define LAN9303_CHIP_REV 0x14
31# define LAN9303_CHIP_ID 0x9303
32#define LAN9303_IRQ_CFG 0x15
33# define LAN9303_IRQ_CFG_IRQ_ENABLE BIT(8)
34# define LAN9303_IRQ_CFG_IRQ_POL BIT(4)
35# define LAN9303_IRQ_CFG_IRQ_TYPE BIT(0)
36#define LAN9303_INT_STS 0x16
37# define LAN9303_INT_STS_PHY_INT2 BIT(27)
38# define LAN9303_INT_STS_PHY_INT1 BIT(26)
39#define LAN9303_INT_EN 0x17
40# define LAN9303_INT_EN_PHY_INT2_EN BIT(27)
41# define LAN9303_INT_EN_PHY_INT1_EN BIT(26)
42#define LAN9303_HW_CFG 0x1D
43# define LAN9303_HW_CFG_READY BIT(27)
44# define LAN9303_HW_CFG_AMDX_EN_PORT2 BIT(26)
45# define LAN9303_HW_CFG_AMDX_EN_PORT1 BIT(25)
46#define LAN9303_PMI_DATA 0x29
47#define LAN9303_PMI_ACCESS 0x2A
48# define LAN9303_PMI_ACCESS_PHY_ADDR(x) (((x) & 0x1f) << 11)
49# define LAN9303_PMI_ACCESS_MIIRINDA(x) (((x) & 0x1f) << 6)
50# define LAN9303_PMI_ACCESS_MII_BUSY BIT(0)
51# define LAN9303_PMI_ACCESS_MII_WRITE BIT(1)
52#define LAN9303_MANUAL_FC_1 0x68
53#define LAN9303_MANUAL_FC_2 0x69
54#define LAN9303_MANUAL_FC_0 0x6a
55#define LAN9303_SWITCH_CSR_DATA 0x6b
56#define LAN9303_SWITCH_CSR_CMD 0x6c
57#define LAN9303_SWITCH_CSR_CMD_BUSY BIT(31)
58#define LAN9303_SWITCH_CSR_CMD_RW BIT(30)
59#define LAN9303_SWITCH_CSR_CMD_LANES (BIT(19) | BIT(18) | BIT(17) | BIT(16))
60#define LAN9303_VIRT_PHY_BASE 0x70
61#define LAN9303_VIRT_SPECIAL_CTRL 0x77
Egil Hjelmeland4d6a78b2017-09-19 10:09:24 +020062#define LAN9303_VIRT_SPECIAL_TURBO BIT(10) /*Turbo MII Enable*/
Juergen Beiserta1292592017-04-18 10:48:25 +020063
Egil Hjelmelandab78acb2017-07-30 19:58:54 +020064/*13.4 Switch Fabric Control and Status Registers
65 * Accessed indirectly via SWITCH_CSR_CMD, SWITCH_CSR_DATA.
66 */
Juergen Beiserta1292592017-04-18 10:48:25 +020067#define LAN9303_SW_DEV_ID 0x0000
68#define LAN9303_SW_RESET 0x0001
69#define LAN9303_SW_RESET_RESET BIT(0)
70#define LAN9303_SW_IMR 0x0004
71#define LAN9303_SW_IPR 0x0005
72#define LAN9303_MAC_VER_ID_0 0x0400
73#define LAN9303_MAC_RX_CFG_0 0x0401
74# define LAN9303_MAC_RX_CFG_X_REJECT_MAC_TYPES BIT(1)
75# define LAN9303_MAC_RX_CFG_X_RX_ENABLE BIT(0)
76#define LAN9303_MAC_RX_UNDSZE_CNT_0 0x0410
77#define LAN9303_MAC_RX_64_CNT_0 0x0411
78#define LAN9303_MAC_RX_127_CNT_0 0x0412
79#define LAN9303_MAC_RX_255_CNT_0 0x413
80#define LAN9303_MAC_RX_511_CNT_0 0x0414
81#define LAN9303_MAC_RX_1023_CNT_0 0x0415
82#define LAN9303_MAC_RX_MAX_CNT_0 0x0416
83#define LAN9303_MAC_RX_OVRSZE_CNT_0 0x0417
84#define LAN9303_MAC_RX_PKTOK_CNT_0 0x0418
85#define LAN9303_MAC_RX_CRCERR_CNT_0 0x0419
86#define LAN9303_MAC_RX_MULCST_CNT_0 0x041a
87#define LAN9303_MAC_RX_BRDCST_CNT_0 0x041b
88#define LAN9303_MAC_RX_PAUSE_CNT_0 0x041c
89#define LAN9303_MAC_RX_FRAG_CNT_0 0x041d
90#define LAN9303_MAC_RX_JABB_CNT_0 0x041e
91#define LAN9303_MAC_RX_ALIGN_CNT_0 0x041f
92#define LAN9303_MAC_RX_PKTLEN_CNT_0 0x0420
93#define LAN9303_MAC_RX_GOODPKTLEN_CNT_0 0x0421
94#define LAN9303_MAC_RX_SYMBL_CNT_0 0x0422
95#define LAN9303_MAC_RX_CTLFRM_CNT_0 0x0423
96
97#define LAN9303_MAC_TX_CFG_0 0x0440
98# define LAN9303_MAC_TX_CFG_X_TX_IFG_CONFIG_DEFAULT (21 << 2)
99# define LAN9303_MAC_TX_CFG_X_TX_PAD_ENABLE BIT(1)
100# define LAN9303_MAC_TX_CFG_X_TX_ENABLE BIT(0)
101#define LAN9303_MAC_TX_DEFER_CNT_0 0x0451
102#define LAN9303_MAC_TX_PAUSE_CNT_0 0x0452
103#define LAN9303_MAC_TX_PKTOK_CNT_0 0x0453
104#define LAN9303_MAC_TX_64_CNT_0 0x0454
105#define LAN9303_MAC_TX_127_CNT_0 0x0455
106#define LAN9303_MAC_TX_255_CNT_0 0x0456
107#define LAN9303_MAC_TX_511_CNT_0 0x0457
108#define LAN9303_MAC_TX_1023_CNT_0 0x0458
109#define LAN9303_MAC_TX_MAX_CNT_0 0x0459
110#define LAN9303_MAC_TX_UNDSZE_CNT_0 0x045a
111#define LAN9303_MAC_TX_PKTLEN_CNT_0 0x045c
112#define LAN9303_MAC_TX_BRDCST_CNT_0 0x045d
113#define LAN9303_MAC_TX_MULCST_CNT_0 0x045e
114#define LAN9303_MAC_TX_LATECOL_0 0x045f
115#define LAN9303_MAC_TX_EXCOL_CNT_0 0x0460
116#define LAN9303_MAC_TX_SNGLECOL_CNT_0 0x0461
117#define LAN9303_MAC_TX_MULTICOL_CNT_0 0x0462
118#define LAN9303_MAC_TX_TOTALCOL_CNT_0 0x0463
119
120#define LAN9303_MAC_VER_ID_1 0x0800
121#define LAN9303_MAC_RX_CFG_1 0x0801
122#define LAN9303_MAC_TX_CFG_1 0x0840
123#define LAN9303_MAC_VER_ID_2 0x0c00
124#define LAN9303_MAC_RX_CFG_2 0x0c01
125#define LAN9303_MAC_TX_CFG_2 0x0c40
126#define LAN9303_SWE_ALR_CMD 0x1800
127#define LAN9303_SWE_VLAN_CMD 0x180b
128# define LAN9303_SWE_VLAN_CMD_RNW BIT(5)
129# define LAN9303_SWE_VLAN_CMD_PVIDNVLAN BIT(4)
130#define LAN9303_SWE_VLAN_WR_DATA 0x180c
131#define LAN9303_SWE_VLAN_RD_DATA 0x180e
132# define LAN9303_SWE_VLAN_MEMBER_PORT2 BIT(17)
133# define LAN9303_SWE_VLAN_UNTAG_PORT2 BIT(16)
134# define LAN9303_SWE_VLAN_MEMBER_PORT1 BIT(15)
135# define LAN9303_SWE_VLAN_UNTAG_PORT1 BIT(14)
136# define LAN9303_SWE_VLAN_MEMBER_PORT0 BIT(13)
137# define LAN9303_SWE_VLAN_UNTAG_PORT0 BIT(12)
138#define LAN9303_SWE_VLAN_CMD_STS 0x1810
139#define LAN9303_SWE_GLB_INGRESS_CFG 0x1840
140#define LAN9303_SWE_PORT_STATE 0x1843
141# define LAN9303_SWE_PORT_STATE_FORWARDING_PORT2 (0)
142# define LAN9303_SWE_PORT_STATE_LEARNING_PORT2 BIT(5)
143# define LAN9303_SWE_PORT_STATE_BLOCKING_PORT2 BIT(4)
144# define LAN9303_SWE_PORT_STATE_FORWARDING_PORT1 (0)
145# define LAN9303_SWE_PORT_STATE_LEARNING_PORT1 BIT(3)
146# define LAN9303_SWE_PORT_STATE_BLOCKING_PORT1 BIT(2)
147# define LAN9303_SWE_PORT_STATE_FORWARDING_PORT0 (0)
148# define LAN9303_SWE_PORT_STATE_LEARNING_PORT0 BIT(1)
149# define LAN9303_SWE_PORT_STATE_BLOCKING_PORT0 BIT(0)
Egil Hjelmelandd99a86a2017-10-10 14:49:53 +0200150# define LAN9303_SWE_PORT_STATE_DISABLED_PORT0 (3)
Juergen Beiserta1292592017-04-18 10:48:25 +0200151#define LAN9303_SWE_PORT_MIRROR 0x1846
152# define LAN9303_SWE_PORT_MIRROR_SNIFF_ALL BIT(8)
153# define LAN9303_SWE_PORT_MIRROR_SNIFFER_PORT2 BIT(7)
154# define LAN9303_SWE_PORT_MIRROR_SNIFFER_PORT1 BIT(6)
155# define LAN9303_SWE_PORT_MIRROR_SNIFFER_PORT0 BIT(5)
156# define LAN9303_SWE_PORT_MIRROR_MIRRORED_PORT2 BIT(4)
157# define LAN9303_SWE_PORT_MIRROR_MIRRORED_PORT1 BIT(3)
158# define LAN9303_SWE_PORT_MIRROR_MIRRORED_PORT0 BIT(2)
159# define LAN9303_SWE_PORT_MIRROR_ENABLE_RX_MIRRORING BIT(1)
160# define LAN9303_SWE_PORT_MIRROR_ENABLE_TX_MIRRORING BIT(0)
Egil Hjelmelandd99a86a2017-10-10 14:49:53 +0200161# define LAN9303_SWE_PORT_MIRROR_DISABLED 0
Juergen Beiserta1292592017-04-18 10:48:25 +0200162#define LAN9303_SWE_INGRESS_PORT_TYPE 0x1847
Egil Hjelmelandf7e3bfa2017-10-10 14:49:52 +0200163#define LAN9303_SWE_INGRESS_PORT_TYPE_VLAN 3
Juergen Beiserta1292592017-04-18 10:48:25 +0200164#define LAN9303_BM_CFG 0x1c00
165#define LAN9303_BM_EGRSS_PORT_TYPE 0x1c0c
166# define LAN9303_BM_EGRSS_PORT_TYPE_SPECIAL_TAG_PORT2 (BIT(17) | BIT(16))
167# define LAN9303_BM_EGRSS_PORT_TYPE_SPECIAL_TAG_PORT1 (BIT(9) | BIT(8))
168# define LAN9303_BM_EGRSS_PORT_TYPE_SPECIAL_TAG_PORT0 (BIT(1) | BIT(0))
169
Egil Hjelmeland451d3ca2017-08-05 13:05:46 +0200170#define LAN9303_SWITCH_PORT_REG(port, reg0) (0x400 * (port) + (reg0))
Juergen Beiserta1292592017-04-18 10:48:25 +0200171
172/* the built-in PHYs are of type LAN911X */
173#define MII_LAN911X_SPECIAL_MODES 0x12
174#define MII_LAN911X_SPECIAL_CONTROL_STATUS 0x1f
175
176static const struct regmap_range lan9303_valid_regs[] = {
177 regmap_reg_range(0x14, 0x17), /* misc, interrupt */
178 regmap_reg_range(0x19, 0x19), /* endian test */
179 regmap_reg_range(0x1d, 0x1d), /* hardware config */
180 regmap_reg_range(0x23, 0x24), /* general purpose timer */
181 regmap_reg_range(0x27, 0x27), /* counter */
182 regmap_reg_range(0x29, 0x2a), /* PMI index regs */
183 regmap_reg_range(0x68, 0x6a), /* flow control */
184 regmap_reg_range(0x6b, 0x6c), /* switch fabric indirect regs */
185 regmap_reg_range(0x6d, 0x6f), /* misc */
186 regmap_reg_range(0x70, 0x77), /* virtual phy */
187 regmap_reg_range(0x78, 0x7a), /* GPIO */
188 regmap_reg_range(0x7c, 0x7e), /* MAC & reset */
189 regmap_reg_range(0x80, 0xb7), /* switch fabric direct regs (wr only) */
190};
191
192static const struct regmap_range lan9303_reserved_ranges[] = {
193 regmap_reg_range(0x00, 0x13),
194 regmap_reg_range(0x18, 0x18),
195 regmap_reg_range(0x1a, 0x1c),
196 regmap_reg_range(0x1e, 0x22),
197 regmap_reg_range(0x25, 0x26),
198 regmap_reg_range(0x28, 0x28),
199 regmap_reg_range(0x2b, 0x67),
200 regmap_reg_range(0x7b, 0x7b),
201 regmap_reg_range(0x7f, 0x7f),
202 regmap_reg_range(0xb8, 0xff),
203};
204
205const struct regmap_access_table lan9303_register_set = {
206 .yes_ranges = lan9303_valid_regs,
207 .n_yes_ranges = ARRAY_SIZE(lan9303_valid_regs),
208 .no_ranges = lan9303_reserved_ranges,
209 .n_no_ranges = ARRAY_SIZE(lan9303_reserved_ranges),
210};
211EXPORT_SYMBOL(lan9303_register_set);
212
213static int lan9303_read(struct regmap *regmap, unsigned int offset, u32 *reg)
214{
215 int ret, i;
216
217 /* we can lose arbitration for the I2C case, because the device
218 * tries to detect and read an external EEPROM after reset and acts as
219 * a master on the shared I2C bus itself. This conflicts with our
220 * attempts to access the device as a slave at the same moment.
221 */
222 for (i = 0; i < 5; i++) {
223 ret = regmap_read(regmap, offset, reg);
224 if (!ret)
225 return 0;
226 if (ret != -EAGAIN)
227 break;
228 msleep(500);
229 }
230
231 return -EIO;
232}
233
234static int lan9303_virt_phy_reg_read(struct lan9303 *chip, int regnum)
235{
236 int ret;
237 u32 val;
238
239 if (regnum > MII_EXPANSION)
240 return -EINVAL;
241
242 ret = lan9303_read(chip->regmap, LAN9303_VIRT_PHY_BASE + regnum, &val);
243 if (ret)
244 return ret;
245
246 return val & 0xffff;
247}
248
249static int lan9303_virt_phy_reg_write(struct lan9303 *chip, int regnum, u16 val)
250{
251 if (regnum > MII_EXPANSION)
252 return -EINVAL;
253
254 return regmap_write(chip->regmap, LAN9303_VIRT_PHY_BASE + regnum, val);
255}
256
Egil Hjelmeland9e866e52017-07-30 19:58:55 +0200257static int lan9303_indirect_phy_wait_for_completion(struct lan9303 *chip)
Juergen Beiserta1292592017-04-18 10:48:25 +0200258{
259 int ret, i;
260 u32 reg;
261
262 for (i = 0; i < 25; i++) {
263 ret = lan9303_read(chip->regmap, LAN9303_PMI_ACCESS, &reg);
264 if (ret) {
265 dev_err(chip->dev,
266 "Failed to read pmi access status: %d\n", ret);
267 return ret;
268 }
269 if (!(reg & LAN9303_PMI_ACCESS_MII_BUSY))
270 return 0;
271 msleep(1);
272 }
273
274 return -EIO;
275}
276
Egil Hjelmeland9e866e52017-07-30 19:58:55 +0200277static int lan9303_indirect_phy_read(struct lan9303 *chip, int addr, int regnum)
Juergen Beiserta1292592017-04-18 10:48:25 +0200278{
279 int ret;
280 u32 val;
281
282 val = LAN9303_PMI_ACCESS_PHY_ADDR(addr);
283 val |= LAN9303_PMI_ACCESS_MIIRINDA(regnum);
284
285 mutex_lock(&chip->indirect_mutex);
286
Egil Hjelmeland9e866e52017-07-30 19:58:55 +0200287 ret = lan9303_indirect_phy_wait_for_completion(chip);
Juergen Beiserta1292592017-04-18 10:48:25 +0200288 if (ret)
289 goto on_error;
290
291 /* start the MII read cycle */
292 ret = regmap_write(chip->regmap, LAN9303_PMI_ACCESS, val);
293 if (ret)
294 goto on_error;
295
Egil Hjelmeland9e866e52017-07-30 19:58:55 +0200296 ret = lan9303_indirect_phy_wait_for_completion(chip);
Juergen Beiserta1292592017-04-18 10:48:25 +0200297 if (ret)
298 goto on_error;
299
300 /* read the result of this operation */
301 ret = lan9303_read(chip->regmap, LAN9303_PMI_DATA, &val);
302 if (ret)
303 goto on_error;
304
305 mutex_unlock(&chip->indirect_mutex);
306
307 return val & 0xffff;
308
309on_error:
310 mutex_unlock(&chip->indirect_mutex);
311 return ret;
312}
313
Egil Hjelmeland9e866e52017-07-30 19:58:55 +0200314static int lan9303_indirect_phy_write(struct lan9303 *chip, int addr,
315 int regnum, u16 val)
Juergen Beiserta1292592017-04-18 10:48:25 +0200316{
317 int ret;
318 u32 reg;
319
320 reg = LAN9303_PMI_ACCESS_PHY_ADDR(addr);
321 reg |= LAN9303_PMI_ACCESS_MIIRINDA(regnum);
322 reg |= LAN9303_PMI_ACCESS_MII_WRITE;
323
324 mutex_lock(&chip->indirect_mutex);
325
Egil Hjelmeland9e866e52017-07-30 19:58:55 +0200326 ret = lan9303_indirect_phy_wait_for_completion(chip);
Juergen Beiserta1292592017-04-18 10:48:25 +0200327 if (ret)
328 goto on_error;
329
330 /* write the data first... */
331 ret = regmap_write(chip->regmap, LAN9303_PMI_DATA, val);
332 if (ret)
333 goto on_error;
334
335 /* ...then start the MII write cycle */
336 ret = regmap_write(chip->regmap, LAN9303_PMI_ACCESS, reg);
337
338on_error:
339 mutex_unlock(&chip->indirect_mutex);
340 return ret;
341}
342
Egil Hjelmeland2c340892017-07-30 19:58:56 +0200343const struct lan9303_phy_ops lan9303_indirect_phy_ops = {
344 .phy_read = lan9303_indirect_phy_read,
345 .phy_write = lan9303_indirect_phy_write,
346};
347EXPORT_SYMBOL_GPL(lan9303_indirect_phy_ops);
348
Juergen Beiserta1292592017-04-18 10:48:25 +0200349static int lan9303_switch_wait_for_completion(struct lan9303 *chip)
350{
351 int ret, i;
352 u32 reg;
353
354 for (i = 0; i < 25; i++) {
355 ret = lan9303_read(chip->regmap, LAN9303_SWITCH_CSR_CMD, &reg);
356 if (ret) {
357 dev_err(chip->dev,
358 "Failed to read csr command status: %d\n", ret);
359 return ret;
360 }
361 if (!(reg & LAN9303_SWITCH_CSR_CMD_BUSY))
362 return 0;
363 msleep(1);
364 }
365
366 return -EIO;
367}
368
369static int lan9303_write_switch_reg(struct lan9303 *chip, u16 regnum, u32 val)
370{
371 u32 reg;
372 int ret;
373
374 reg = regnum;
375 reg |= LAN9303_SWITCH_CSR_CMD_LANES;
376 reg |= LAN9303_SWITCH_CSR_CMD_BUSY;
377
378 mutex_lock(&chip->indirect_mutex);
379
380 ret = lan9303_switch_wait_for_completion(chip);
381 if (ret)
382 goto on_error;
383
384 ret = regmap_write(chip->regmap, LAN9303_SWITCH_CSR_DATA, val);
385 if (ret) {
386 dev_err(chip->dev, "Failed to write csr data reg: %d\n", ret);
387 goto on_error;
388 }
389
390 /* trigger write */
391 ret = regmap_write(chip->regmap, LAN9303_SWITCH_CSR_CMD, reg);
392 if (ret)
393 dev_err(chip->dev, "Failed to write csr command reg: %d\n",
394 ret);
395
396on_error:
397 mutex_unlock(&chip->indirect_mutex);
398 return ret;
399}
400
401static int lan9303_read_switch_reg(struct lan9303 *chip, u16 regnum, u32 *val)
402{
403 u32 reg;
404 int ret;
405
406 reg = regnum;
407 reg |= LAN9303_SWITCH_CSR_CMD_LANES;
408 reg |= LAN9303_SWITCH_CSR_CMD_RW;
409 reg |= LAN9303_SWITCH_CSR_CMD_BUSY;
410
411 mutex_lock(&chip->indirect_mutex);
412
413 ret = lan9303_switch_wait_for_completion(chip);
414 if (ret)
415 goto on_error;
416
417 /* trigger read */
418 ret = regmap_write(chip->regmap, LAN9303_SWITCH_CSR_CMD, reg);
419 if (ret) {
420 dev_err(chip->dev, "Failed to write csr command reg: %d\n",
421 ret);
422 goto on_error;
423 }
424
425 ret = lan9303_switch_wait_for_completion(chip);
426 if (ret)
427 goto on_error;
428
429 ret = lan9303_read(chip->regmap, LAN9303_SWITCH_CSR_DATA, val);
430 if (ret)
431 dev_err(chip->dev, "Failed to read csr data reg: %d\n", ret);
432on_error:
433 mutex_unlock(&chip->indirect_mutex);
434 return ret;
435}
436
Egil Hjelmeland451d3ca2017-08-05 13:05:46 +0200437static int lan9303_write_switch_port(struct lan9303 *chip, int port,
438 u16 regnum, u32 val)
439{
440 return lan9303_write_switch_reg(
441 chip, LAN9303_SWITCH_PORT_REG(port, regnum), val);
442}
443
Egil Hjelmeland0a967b42017-08-05 13:05:50 +0200444static int lan9303_read_switch_port(struct lan9303 *chip, int port,
445 u16 regnum, u32 *val)
446{
447 return lan9303_read_switch_reg(
448 chip, LAN9303_SWITCH_PORT_REG(port, regnum), val);
449}
450
Juergen Beiserta1292592017-04-18 10:48:25 +0200451static int lan9303_detect_phy_setup(struct lan9303 *chip)
452{
453 int reg;
454
455 /* depending on the 'phy_addr_sel_strap' setting, the three phys are
456 * using IDs 0-1-2 or IDs 1-2-3. We cannot read back the
457 * 'phy_addr_sel_strap' setting directly, so we need a test, which
458 * configuration is active:
459 * Special reg 18 of phy 3 reads as 0x0000, if 'phy_addr_sel_strap' is 0
460 * and the IDs are 0-1-2, else it contains something different from
461 * 0x0000, which means 'phy_addr_sel_strap' is 1 and the IDs are 1-2-3.
Egil Hjelmelandd329ac82017-07-30 19:58:53 +0200462 * 0xffff is returned on MDIO read with no response.
Juergen Beiserta1292592017-04-18 10:48:25 +0200463 */
Egil Hjelmeland2c340892017-07-30 19:58:56 +0200464 reg = chip->ops->phy_read(chip, 3, MII_LAN911X_SPECIAL_MODES);
Juergen Beiserta1292592017-04-18 10:48:25 +0200465 if (reg < 0) {
466 dev_err(chip->dev, "Failed to detect phy config: %d\n", reg);
467 return reg;
468 }
469
Egil Hjelmelandd329ac82017-07-30 19:58:53 +0200470 if ((reg != 0) && (reg != 0xffff))
Juergen Beiserta1292592017-04-18 10:48:25 +0200471 chip->phy_addr_sel_strap = 1;
472 else
473 chip->phy_addr_sel_strap = 0;
474
475 dev_dbg(chip->dev, "Phy setup '%s' detected\n",
476 chip->phy_addr_sel_strap ? "1-2-3" : "0-1-2");
477
478 return 0;
479}
480
Egil Hjelmeland9c842582017-08-05 13:05:49 +0200481static int lan9303_disable_processing_port(struct lan9303 *chip,
482 unsigned int port)
Juergen Beiserta1292592017-04-18 10:48:25 +0200483{
484 int ret;
485
486 /* disable RX, but keep register reset default values else */
Egil Hjelmeland451d3ca2017-08-05 13:05:46 +0200487 ret = lan9303_write_switch_port(chip, port, LAN9303_MAC_RX_CFG_0,
488 LAN9303_MAC_RX_CFG_X_REJECT_MAC_TYPES);
Juergen Beiserta1292592017-04-18 10:48:25 +0200489 if (ret)
490 return ret;
491
492 /* disable TX, but keep register reset default values else */
Egil Hjelmeland451d3ca2017-08-05 13:05:46 +0200493 return lan9303_write_switch_port(chip, port, LAN9303_MAC_TX_CFG_0,
Juergen Beiserta1292592017-04-18 10:48:25 +0200494 LAN9303_MAC_TX_CFG_X_TX_IFG_CONFIG_DEFAULT |
495 LAN9303_MAC_TX_CFG_X_TX_PAD_ENABLE);
496}
497
Egil Hjelmeland9c842582017-08-05 13:05:49 +0200498static int lan9303_enable_processing_port(struct lan9303 *chip,
499 unsigned int port)
Juergen Beiserta1292592017-04-18 10:48:25 +0200500{
501 int ret;
502
503 /* enable RX and keep register reset default values else */
Egil Hjelmeland451d3ca2017-08-05 13:05:46 +0200504 ret = lan9303_write_switch_port(chip, port, LAN9303_MAC_RX_CFG_0,
505 LAN9303_MAC_RX_CFG_X_REJECT_MAC_TYPES |
506 LAN9303_MAC_RX_CFG_X_RX_ENABLE);
Juergen Beiserta1292592017-04-18 10:48:25 +0200507 if (ret)
508 return ret;
509
510 /* enable TX and keep register reset default values else */
Egil Hjelmeland451d3ca2017-08-05 13:05:46 +0200511 return lan9303_write_switch_port(chip, port, LAN9303_MAC_TX_CFG_0,
Juergen Beiserta1292592017-04-18 10:48:25 +0200512 LAN9303_MAC_TX_CFG_X_TX_IFG_CONFIG_DEFAULT |
513 LAN9303_MAC_TX_CFG_X_TX_PAD_ENABLE |
514 LAN9303_MAC_TX_CFG_X_TX_ENABLE);
515}
516
Egil Hjelmelandf7e3bfa2017-10-10 14:49:52 +0200517/* forward special tagged packets from port 0 to port 1 *or* port 2 */
518static int lan9303_setup_tagging(struct lan9303 *chip)
519{
520 int ret;
521 u32 val;
522 /* enable defining the destination port via special VLAN tagging
523 * for port 0
524 */
525 ret = lan9303_write_switch_reg(chip, LAN9303_SWE_INGRESS_PORT_TYPE,
526 LAN9303_SWE_INGRESS_PORT_TYPE_VLAN);
527 if (ret)
528 return ret;
529
530 /* tag incoming packets at port 1 and 2 on their way to port 0 to be
531 * able to discover their source port
532 */
533 val = LAN9303_BM_EGRSS_PORT_TYPE_SPECIAL_TAG_PORT0;
534 return lan9303_write_switch_reg(chip, LAN9303_BM_EGRSS_PORT_TYPE, val);
535}
536
Juergen Beiserta1292592017-04-18 10:48:25 +0200537/* We want a special working switch:
538 * - do not forward packets between port 1 and 2
539 * - forward everything from port 1 to port 0
540 * - forward everything from port 2 to port 0
Juergen Beiserta1292592017-04-18 10:48:25 +0200541 */
542static int lan9303_separate_ports(struct lan9303 *chip)
543{
544 int ret;
545
546 ret = lan9303_write_switch_reg(chip, LAN9303_SWE_PORT_MIRROR,
547 LAN9303_SWE_PORT_MIRROR_SNIFFER_PORT0 |
548 LAN9303_SWE_PORT_MIRROR_MIRRORED_PORT1 |
549 LAN9303_SWE_PORT_MIRROR_MIRRORED_PORT2 |
550 LAN9303_SWE_PORT_MIRROR_ENABLE_RX_MIRRORING |
551 LAN9303_SWE_PORT_MIRROR_SNIFF_ALL);
552 if (ret)
553 return ret;
554
Juergen Beiserta1292592017-04-18 10:48:25 +0200555 /* prevent port 1 and 2 from forwarding packets by their own */
556 return lan9303_write_switch_reg(chip, LAN9303_SWE_PORT_STATE,
557 LAN9303_SWE_PORT_STATE_FORWARDING_PORT0 |
558 LAN9303_SWE_PORT_STATE_BLOCKING_PORT1 |
559 LAN9303_SWE_PORT_STATE_BLOCKING_PORT2);
560}
561
Egil Hjelmelandd99a86a2017-10-10 14:49:53 +0200562static void lan9303_bridge_ports(struct lan9303 *chip)
563{
564 /* ports bridged: remove mirroring */
565 lan9303_write_switch_reg(chip, LAN9303_SWE_PORT_MIRROR,
566 LAN9303_SWE_PORT_MIRROR_DISABLED);
567
568 lan9303_write_switch_reg(chip, LAN9303_SWE_PORT_STATE,
569 chip->swe_port_state);
570}
571
Juergen Beiserta1292592017-04-18 10:48:25 +0200572static int lan9303_handle_reset(struct lan9303 *chip)
573{
574 if (!chip->reset_gpio)
575 return 0;
576
577 if (chip->reset_duration != 0)
578 msleep(chip->reset_duration);
579
580 /* release (deassert) reset and activate the device */
581 gpiod_set_value_cansleep(chip->reset_gpio, 0);
582
583 return 0;
584}
585
586/* stop processing packets for all ports */
587static int lan9303_disable_processing(struct lan9303 *chip)
588{
Egil Hjelmelandb3d14a22017-08-05 13:05:48 +0200589 int p;
Juergen Beiserta1292592017-04-18 10:48:25 +0200590
Egil Hjelmelandb3d14a22017-08-05 13:05:48 +0200591 for (p = 0; p < LAN9303_NUM_PORTS; p++) {
Egil Hjelmeland9c842582017-08-05 13:05:49 +0200592 int ret = lan9303_disable_processing_port(chip, p);
Egil Hjelmelandb3d14a22017-08-05 13:05:48 +0200593
594 if (ret)
595 return ret;
596 }
597
598 return 0;
Juergen Beiserta1292592017-04-18 10:48:25 +0200599}
600
601static int lan9303_check_device(struct lan9303 *chip)
602{
603 int ret;
604 u32 reg;
605
606 ret = lan9303_read(chip->regmap, LAN9303_CHIP_REV, &reg);
607 if (ret) {
608 dev_err(chip->dev, "failed to read chip revision register: %d\n",
609 ret);
610 if (!chip->reset_gpio) {
611 dev_dbg(chip->dev,
612 "hint: maybe failed due to missing reset GPIO\n");
613 }
614 return ret;
615 }
616
617 if ((reg >> 16) != LAN9303_CHIP_ID) {
618 dev_err(chip->dev, "expecting LAN9303 chip, but found: %X\n",
619 reg >> 16);
620 return ret;
621 }
622
623 /* The default state of the LAN9303 device is to forward packets between
624 * all ports (if not configured differently by an external EEPROM).
625 * The initial state of a DSA device must be forwarding packets only
626 * between the external and the internal ports and no forwarding
627 * between the external ports. In preparation we stop packet handling
628 * at all for now until the LAN9303 device is re-programmed accordingly.
629 */
630 ret = lan9303_disable_processing(chip);
631 if (ret)
632 dev_warn(chip->dev, "failed to disable switching %d\n", ret);
633
634 dev_info(chip->dev, "Found LAN9303 rev. %u\n", reg & 0xffff);
635
636 ret = lan9303_detect_phy_setup(chip);
637 if (ret) {
638 dev_err(chip->dev,
639 "failed to discover phy bootstrap setup: %d\n", ret);
640 return ret;
641 }
642
643 return 0;
644}
645
646/* ---------------------------- DSA -----------------------------------*/
647
648static enum dsa_tag_protocol lan9303_get_tag_protocol(struct dsa_switch *ds)
649{
650 return DSA_TAG_PROTO_LAN9303;
651}
652
653static int lan9303_setup(struct dsa_switch *ds)
654{
655 struct lan9303 *chip = ds->priv;
656 int ret;
657
658 /* Make sure that port 0 is the cpu port */
659 if (!dsa_is_cpu_port(ds, 0)) {
660 dev_err(chip->dev, "port 0 is not the CPU port\n");
661 return -EINVAL;
662 }
663
Egil Hjelmelandf7e3bfa2017-10-10 14:49:52 +0200664 ret = lan9303_setup_tagging(chip);
665 if (ret)
666 dev_err(chip->dev, "failed to setup port tagging %d\n", ret);
667
Juergen Beiserta1292592017-04-18 10:48:25 +0200668 ret = lan9303_separate_ports(chip);
669 if (ret)
670 dev_err(chip->dev, "failed to separate ports %d\n", ret);
671
Egil Hjelmeland9c842582017-08-05 13:05:49 +0200672 ret = lan9303_enable_processing_port(chip, 0);
Juergen Beiserta1292592017-04-18 10:48:25 +0200673 if (ret)
674 dev_err(chip->dev, "failed to re-enable switching %d\n", ret);
675
676 return 0;
677}
678
679struct lan9303_mib_desc {
680 unsigned int offset; /* offset of first MAC */
681 const char *name;
682};
683
684static const struct lan9303_mib_desc lan9303_mib[] = {
685 { .offset = LAN9303_MAC_RX_BRDCST_CNT_0, .name = "RxBroad", },
686 { .offset = LAN9303_MAC_RX_PAUSE_CNT_0, .name = "RxPause", },
687 { .offset = LAN9303_MAC_RX_MULCST_CNT_0, .name = "RxMulti", },
688 { .offset = LAN9303_MAC_RX_PKTOK_CNT_0, .name = "RxOk", },
689 { .offset = LAN9303_MAC_RX_CRCERR_CNT_0, .name = "RxCrcErr", },
690 { .offset = LAN9303_MAC_RX_ALIGN_CNT_0, .name = "RxAlignErr", },
691 { .offset = LAN9303_MAC_RX_JABB_CNT_0, .name = "RxJabber", },
692 { .offset = LAN9303_MAC_RX_FRAG_CNT_0, .name = "RxFragment", },
693 { .offset = LAN9303_MAC_RX_64_CNT_0, .name = "Rx64Byte", },
694 { .offset = LAN9303_MAC_RX_127_CNT_0, .name = "Rx128Byte", },
695 { .offset = LAN9303_MAC_RX_255_CNT_0, .name = "Rx256Byte", },
696 { .offset = LAN9303_MAC_RX_511_CNT_0, .name = "Rx512Byte", },
697 { .offset = LAN9303_MAC_RX_1023_CNT_0, .name = "Rx1024Byte", },
698 { .offset = LAN9303_MAC_RX_MAX_CNT_0, .name = "RxMaxByte", },
699 { .offset = LAN9303_MAC_RX_PKTLEN_CNT_0, .name = "RxByteCnt", },
700 { .offset = LAN9303_MAC_RX_SYMBL_CNT_0, .name = "RxSymbolCnt", },
701 { .offset = LAN9303_MAC_RX_CTLFRM_CNT_0, .name = "RxCfs", },
702 { .offset = LAN9303_MAC_RX_OVRSZE_CNT_0, .name = "RxOverFlow", },
703 { .offset = LAN9303_MAC_TX_UNDSZE_CNT_0, .name = "TxShort", },
704 { .offset = LAN9303_MAC_TX_BRDCST_CNT_0, .name = "TxBroad", },
705 { .offset = LAN9303_MAC_TX_PAUSE_CNT_0, .name = "TxPause", },
706 { .offset = LAN9303_MAC_TX_MULCST_CNT_0, .name = "TxMulti", },
707 { .offset = LAN9303_MAC_RX_UNDSZE_CNT_0, .name = "TxUnderRun", },
708 { .offset = LAN9303_MAC_TX_64_CNT_0, .name = "Tx64Byte", },
709 { .offset = LAN9303_MAC_TX_127_CNT_0, .name = "Tx128Byte", },
710 { .offset = LAN9303_MAC_TX_255_CNT_0, .name = "Tx256Byte", },
711 { .offset = LAN9303_MAC_TX_511_CNT_0, .name = "Tx512Byte", },
712 { .offset = LAN9303_MAC_TX_1023_CNT_0, .name = "Tx1024Byte", },
713 { .offset = LAN9303_MAC_TX_MAX_CNT_0, .name = "TxMaxByte", },
714 { .offset = LAN9303_MAC_TX_PKTLEN_CNT_0, .name = "TxByteCnt", },
715 { .offset = LAN9303_MAC_TX_PKTOK_CNT_0, .name = "TxOk", },
716 { .offset = LAN9303_MAC_TX_TOTALCOL_CNT_0, .name = "TxCollision", },
717 { .offset = LAN9303_MAC_TX_MULTICOL_CNT_0, .name = "TxMultiCol", },
718 { .offset = LAN9303_MAC_TX_SNGLECOL_CNT_0, .name = "TxSingleCol", },
719 { .offset = LAN9303_MAC_TX_EXCOL_CNT_0, .name = "TxExcCol", },
720 { .offset = LAN9303_MAC_TX_DEFER_CNT_0, .name = "TxDefer", },
721 { .offset = LAN9303_MAC_TX_LATECOL_0, .name = "TxLateCol", },
722};
723
724static void lan9303_get_strings(struct dsa_switch *ds, int port, uint8_t *data)
725{
726 unsigned int u;
727
728 for (u = 0; u < ARRAY_SIZE(lan9303_mib); u++) {
729 strncpy(data + u * ETH_GSTRING_LEN, lan9303_mib[u].name,
730 ETH_GSTRING_LEN);
731 }
732}
733
734static void lan9303_get_ethtool_stats(struct dsa_switch *ds, int port,
735 uint64_t *data)
736{
737 struct lan9303 *chip = ds->priv;
Egil Hjelmeland0a967b42017-08-05 13:05:50 +0200738 unsigned int u;
Juergen Beiserta1292592017-04-18 10:48:25 +0200739
740 for (u = 0; u < ARRAY_SIZE(lan9303_mib); u++) {
Egil Hjelmeland0a967b42017-08-05 13:05:50 +0200741 u32 reg;
742 int ret;
743
744 ret = lan9303_read_switch_port(
745 chip, port, lan9303_mib[u].offset, &reg);
746
Juergen Beiserta1292592017-04-18 10:48:25 +0200747 if (ret)
Egil Hjelmeland0a967b42017-08-05 13:05:50 +0200748 dev_warn(chip->dev, "Reading status port %d reg %u failed\n",
749 port, lan9303_mib[u].offset);
Juergen Beiserta1292592017-04-18 10:48:25 +0200750 data[u] = reg;
751 }
752}
753
754static int lan9303_get_sset_count(struct dsa_switch *ds)
755{
756 return ARRAY_SIZE(lan9303_mib);
757}
758
759static int lan9303_phy_read(struct dsa_switch *ds, int phy, int regnum)
760{
761 struct lan9303 *chip = ds->priv;
762 int phy_base = chip->phy_addr_sel_strap;
763
764 if (phy == phy_base)
765 return lan9303_virt_phy_reg_read(chip, regnum);
766 if (phy > phy_base + 2)
767 return -ENODEV;
768
Egil Hjelmeland2c340892017-07-30 19:58:56 +0200769 return chip->ops->phy_read(chip, phy, regnum);
Juergen Beiserta1292592017-04-18 10:48:25 +0200770}
771
772static int lan9303_phy_write(struct dsa_switch *ds, int phy, int regnum,
773 u16 val)
774{
775 struct lan9303 *chip = ds->priv;
776 int phy_base = chip->phy_addr_sel_strap;
777
778 if (phy == phy_base)
779 return lan9303_virt_phy_reg_write(chip, regnum, val);
780 if (phy > phy_base + 2)
781 return -ENODEV;
782
Egil Hjelmeland2c340892017-07-30 19:58:56 +0200783 return chip->ops->phy_write(chip, phy, regnum, val);
Juergen Beiserta1292592017-04-18 10:48:25 +0200784}
785
Egil Hjelmeland4d6a78b2017-09-19 10:09:24 +0200786static void lan9303_adjust_link(struct dsa_switch *ds, int port,
787 struct phy_device *phydev)
788{
789 struct lan9303 *chip = ds->priv;
790 int ctl, res;
791
792 if (!phy_is_pseudo_fixed_link(phydev))
793 return;
794
795 ctl = lan9303_phy_read(ds, port, MII_BMCR);
796
797 ctl &= ~BMCR_ANENABLE;
798
799 if (phydev->speed == SPEED_100)
800 ctl |= BMCR_SPEED100;
801 else if (phydev->speed == SPEED_10)
802 ctl &= ~BMCR_SPEED100;
803 else
804 dev_err(ds->dev, "unsupported speed: %d\n", phydev->speed);
805
806 if (phydev->duplex == DUPLEX_FULL)
807 ctl |= BMCR_FULLDPLX;
808 else
809 ctl &= ~BMCR_FULLDPLX;
810
811 res = lan9303_phy_write(ds, port, MII_BMCR, ctl);
812
813 if (port == chip->phy_addr_sel_strap) {
814 /* Virtual Phy: Remove Turbo 200Mbit mode */
815 lan9303_read(chip->regmap, LAN9303_VIRT_SPECIAL_CTRL, &ctl);
816
817 ctl &= ~LAN9303_VIRT_SPECIAL_TURBO;
818 res = regmap_write(chip->regmap,
819 LAN9303_VIRT_SPECIAL_CTRL, ctl);
820 }
821}
822
Juergen Beiserta1292592017-04-18 10:48:25 +0200823static int lan9303_port_enable(struct dsa_switch *ds, int port,
824 struct phy_device *phy)
825{
826 struct lan9303 *chip = ds->priv;
827
828 /* enable internal packet processing */
829 switch (port) {
830 case 1:
Juergen Beiserta1292592017-04-18 10:48:25 +0200831 case 2:
Egil Hjelmeland9c842582017-08-05 13:05:49 +0200832 return lan9303_enable_processing_port(chip, port);
Juergen Beiserta1292592017-04-18 10:48:25 +0200833 default:
834 dev_dbg(chip->dev,
835 "Error: request to power up invalid port %d\n", port);
836 }
837
838 return -ENODEV;
839}
840
841static void lan9303_port_disable(struct dsa_switch *ds, int port,
842 struct phy_device *phy)
843{
844 struct lan9303 *chip = ds->priv;
845
846 /* disable internal packet processing */
847 switch (port) {
848 case 1:
Juergen Beiserta1292592017-04-18 10:48:25 +0200849 case 2:
Egil Hjelmeland9c842582017-08-05 13:05:49 +0200850 lan9303_disable_processing_port(chip, port);
Egil Hjelmelandb3d14a22017-08-05 13:05:48 +0200851 lan9303_phy_write(ds, chip->phy_addr_sel_strap + port,
Egil Hjelmeland2c340892017-07-30 19:58:56 +0200852 MII_BMCR, BMCR_PDOWN);
Juergen Beiserta1292592017-04-18 10:48:25 +0200853 break;
854 default:
855 dev_dbg(chip->dev,
856 "Error: request to power down invalid port %d\n", port);
857 }
858}
859
Egil Hjelmelandd99a86a2017-10-10 14:49:53 +0200860static int lan9303_port_bridge_join(struct dsa_switch *ds, int port,
861 struct net_device *br)
862{
863 struct lan9303 *chip = ds->priv;
864
865 dev_dbg(chip->dev, "%s(port %d)\n", __func__, port);
Vivien Didelotc8652c82017-10-16 11:12:19 -0400866 if (dsa_to_port(ds, 1)->bridge_dev == dsa_to_port(ds, 2)->bridge_dev) {
Egil Hjelmelandd99a86a2017-10-10 14:49:53 +0200867 lan9303_bridge_ports(chip);
868 chip->is_bridged = true; /* unleash stp_state_set() */
869 }
870
871 return 0;
872}
873
874static void lan9303_port_bridge_leave(struct dsa_switch *ds, int port,
875 struct net_device *br)
876{
877 struct lan9303 *chip = ds->priv;
878
879 dev_dbg(chip->dev, "%s(port %d)\n", __func__, port);
880 if (chip->is_bridged) {
881 lan9303_separate_ports(chip);
882 chip->is_bridged = false;
883 }
884}
885
886static void lan9303_port_stp_state_set(struct dsa_switch *ds, int port,
887 u8 state)
888{
889 int portmask, portstate;
890 struct lan9303 *chip = ds->priv;
891
892 dev_dbg(chip->dev, "%s(port %d, state %d)\n",
893 __func__, port, state);
894
895 switch (state) {
896 case BR_STATE_DISABLED:
897 portstate = LAN9303_SWE_PORT_STATE_DISABLED_PORT0;
898 break;
899 case BR_STATE_BLOCKING:
900 case BR_STATE_LISTENING:
901 portstate = LAN9303_SWE_PORT_STATE_BLOCKING_PORT0;
902 break;
903 case BR_STATE_LEARNING:
904 portstate = LAN9303_SWE_PORT_STATE_LEARNING_PORT0;
905 break;
906 case BR_STATE_FORWARDING:
907 portstate = LAN9303_SWE_PORT_STATE_FORWARDING_PORT0;
908 break;
909 default:
910 portstate = LAN9303_SWE_PORT_STATE_DISABLED_PORT0;
911 dev_err(chip->dev, "unknown stp state: port %d, state %d\n",
912 port, state);
913 }
914
915 portmask = 0x3 << (port * 2);
916 portstate <<= (port * 2);
917
918 chip->swe_port_state = (chip->swe_port_state & ~portmask) | portstate;
919
920 if (chip->is_bridged)
921 lan9303_write_switch_reg(chip, LAN9303_SWE_PORT_STATE,
922 chip->swe_port_state);
923 /* else: touching SWE_PORT_STATE would break port separation */
924}
925
Bhumika Goyald78d6772017-08-09 10:34:15 +0530926static const struct dsa_switch_ops lan9303_switch_ops = {
Juergen Beiserta1292592017-04-18 10:48:25 +0200927 .get_tag_protocol = lan9303_get_tag_protocol,
928 .setup = lan9303_setup,
929 .get_strings = lan9303_get_strings,
930 .phy_read = lan9303_phy_read,
931 .phy_write = lan9303_phy_write,
Egil Hjelmeland4d6a78b2017-09-19 10:09:24 +0200932 .adjust_link = lan9303_adjust_link,
Juergen Beiserta1292592017-04-18 10:48:25 +0200933 .get_ethtool_stats = lan9303_get_ethtool_stats,
934 .get_sset_count = lan9303_get_sset_count,
935 .port_enable = lan9303_port_enable,
936 .port_disable = lan9303_port_disable,
Egil Hjelmelandd99a86a2017-10-10 14:49:53 +0200937 .port_bridge_join = lan9303_port_bridge_join,
938 .port_bridge_leave = lan9303_port_bridge_leave,
939 .port_stp_state_set = lan9303_port_stp_state_set,
Juergen Beiserta1292592017-04-18 10:48:25 +0200940};
941
942static int lan9303_register_switch(struct lan9303 *chip)
943{
Egil Hjelmeland274cdb42017-08-08 00:22:21 +0200944 chip->ds = dsa_switch_alloc(chip->dev, LAN9303_NUM_PORTS);
Juergen Beiserta1292592017-04-18 10:48:25 +0200945 if (!chip->ds)
946 return -ENOMEM;
947
948 chip->ds->priv = chip;
949 chip->ds->ops = &lan9303_switch_ops;
950 chip->ds->phys_mii_mask = chip->phy_addr_sel_strap ? 0xe : 0x7;
951
Vivien Didelot23c9ee42017-05-26 18:12:51 -0400952 return dsa_register_switch(chip->ds);
Juergen Beiserta1292592017-04-18 10:48:25 +0200953}
954
955static void lan9303_probe_reset_gpio(struct lan9303 *chip,
956 struct device_node *np)
957{
958 chip->reset_gpio = devm_gpiod_get_optional(chip->dev, "reset",
959 GPIOD_OUT_LOW);
960
961 if (!chip->reset_gpio) {
962 dev_dbg(chip->dev, "No reset GPIO defined\n");
963 return;
964 }
965
966 chip->reset_duration = 200;
967
968 if (np) {
969 of_property_read_u32(np, "reset-duration",
970 &chip->reset_duration);
971 } else {
972 dev_dbg(chip->dev, "reset duration defaults to 200 ms\n");
973 }
974
975 /* A sane reset duration should not be longer than 1s */
976 if (chip->reset_duration > 1000)
977 chip->reset_duration = 1000;
978}
979
980int lan9303_probe(struct lan9303 *chip, struct device_node *np)
981{
982 int ret;
983
984 mutex_init(&chip->indirect_mutex);
985
986 lan9303_probe_reset_gpio(chip, np);
987
988 ret = lan9303_handle_reset(chip);
989 if (ret)
990 return ret;
991
992 ret = lan9303_check_device(chip);
993 if (ret)
994 return ret;
995
996 ret = lan9303_register_switch(chip);
997 if (ret) {
998 dev_dbg(chip->dev, "Failed to register switch: %d\n", ret);
999 return ret;
1000 }
1001
1002 return 0;
1003}
1004EXPORT_SYMBOL(lan9303_probe);
1005
1006int lan9303_remove(struct lan9303 *chip)
1007{
1008 int rc;
1009
1010 rc = lan9303_disable_processing(chip);
1011 if (rc != 0)
1012 dev_warn(chip->dev, "shutting down failed\n");
1013
1014 dsa_unregister_switch(chip->ds);
1015
1016 /* assert reset to the whole device to prevent it from doing anything */
1017 gpiod_set_value_cansleep(chip->reset_gpio, 1);
1018 gpiod_unexport(chip->reset_gpio);
1019
1020 return 0;
1021}
1022EXPORT_SYMBOL(lan9303_remove);
1023
1024MODULE_AUTHOR("Juergen Borleis <kernel@pengutronix.de>");
1025MODULE_DESCRIPTION("Core driver for SMSC/Microchip LAN9303 three port ethernet switch");
1026MODULE_LICENSE("GPL v2");