vsc9953.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752
  1. /*
  2. * Copyright 2014 Freescale Semiconductor, Inc.
  3. *
  4. * SPDX-License-Identifier: GPL-2.0+
  5. *
  6. * Driver for the Vitesse VSC9953 L2 Switch
  7. */
  8. #include <asm/io.h>
  9. #include <asm/fsl_serdes.h>
  10. #include <fm_eth.h>
  11. #include <fsl_memac.h>
  12. #include <bitfield.h>
  13. #include <errno.h>
  14. #include <malloc.h>
  15. #include <vsc9953.h>
  16. static struct vsc9953_info vsc9953_l2sw = {
  17. .port[0] = VSC9953_PORT_INFO_INITIALIZER(0),
  18. .port[1] = VSC9953_PORT_INFO_INITIALIZER(1),
  19. .port[2] = VSC9953_PORT_INFO_INITIALIZER(2),
  20. .port[3] = VSC9953_PORT_INFO_INITIALIZER(3),
  21. .port[4] = VSC9953_PORT_INFO_INITIALIZER(4),
  22. .port[5] = VSC9953_PORT_INFO_INITIALIZER(5),
  23. .port[6] = VSC9953_PORT_INFO_INITIALIZER(6),
  24. .port[7] = VSC9953_PORT_INFO_INITIALIZER(7),
  25. .port[8] = VSC9953_PORT_INFO_INITIALIZER(8),
  26. .port[9] = VSC9953_PORT_INFO_INITIALIZER(9),
  27. };
  28. void vsc9953_port_info_set_mdio(int port_no, struct mii_dev *bus)
  29. {
  30. if (!VSC9953_PORT_CHECK(port_no))
  31. return;
  32. vsc9953_l2sw.port[port_no].bus = bus;
  33. }
  34. void vsc9953_port_info_set_phy_address(int port_no, int address)
  35. {
  36. if (!VSC9953_PORT_CHECK(port_no))
  37. return;
  38. vsc9953_l2sw.port[port_no].phyaddr = address;
  39. }
  40. void vsc9953_port_info_set_phy_int(int port_no, phy_interface_t phy_int)
  41. {
  42. if (!VSC9953_PORT_CHECK(port_no))
  43. return;
  44. vsc9953_l2sw.port[port_no].enet_if = phy_int;
  45. }
  46. void vsc9953_port_enable(int port_no)
  47. {
  48. if (!VSC9953_PORT_CHECK(port_no))
  49. return;
  50. vsc9953_l2sw.port[port_no].enabled = 1;
  51. }
  52. void vsc9953_port_disable(int port_no)
  53. {
  54. if (!VSC9953_PORT_CHECK(port_no))
  55. return;
  56. vsc9953_l2sw.port[port_no].enabled = 0;
  57. }
  58. static void vsc9953_mdio_write(struct vsc9953_mii_mng *phyregs, int port_addr,
  59. int regnum, int value)
  60. {
  61. int timeout = 50000;
  62. out_le32(&phyregs->miimcmd, (0x1 << 31) | ((port_addr & 0x1f) << 25) |
  63. ((regnum & 0x1f) << 20) | ((value & 0xffff) << 4) |
  64. (0x1 << 1));
  65. asm("sync");
  66. while ((in_le32(&phyregs->miimstatus) & 0x8) && --timeout)
  67. udelay(1);
  68. if (timeout == 0)
  69. debug("Timeout waiting for MDIO write\n");
  70. }
  71. static int vsc9953_mdio_read(struct vsc9953_mii_mng *phyregs, int port_addr,
  72. int regnum)
  73. {
  74. int value = 0xFFFF;
  75. int timeout = 50000;
  76. while ((in_le32(&phyregs->miimstatus) & MIIMIND_OPR_PEND) && --timeout)
  77. udelay(1);
  78. if (timeout == 0) {
  79. debug("Timeout waiting for MDIO operation to finish\n");
  80. return value;
  81. }
  82. /* Put the address of the phy, and the register
  83. * number into MIICMD
  84. */
  85. out_le32(&phyregs->miimcmd, (0x1 << 31) | ((port_addr & 0x1f) << 25) |
  86. ((regnum & 0x1f) << 20) | ((value & 0xffff) << 4) |
  87. (0x2 << 1));
  88. timeout = 50000;
  89. /* Wait for the the indication that the read is done */
  90. while ((in_le32(&phyregs->miimstatus) & 0x8) && --timeout)
  91. udelay(1);
  92. if (timeout == 0)
  93. debug("Timeout waiting for MDIO read\n");
  94. /* Grab the value read from the PHY */
  95. value = in_le32(&phyregs->miimdata);
  96. if ((value & 0x00030000) == 0)
  97. return value & 0x0000ffff;
  98. return value;
  99. }
  100. static int init_phy(struct eth_device *dev)
  101. {
  102. struct vsc9953_port_info *l2sw_port = dev->priv;
  103. struct phy_device *phydev = NULL;
  104. #ifdef CONFIG_PHYLIB
  105. if (!l2sw_port->bus)
  106. return 0;
  107. phydev = phy_connect(l2sw_port->bus, l2sw_port->phyaddr, dev,
  108. l2sw_port->enet_if);
  109. if (!phydev) {
  110. printf("Failed to connect\n");
  111. return -1;
  112. }
  113. phydev->supported &= SUPPORTED_10baseT_Half |
  114. SUPPORTED_10baseT_Full |
  115. SUPPORTED_100baseT_Half |
  116. SUPPORTED_100baseT_Full |
  117. SUPPORTED_1000baseT_Full;
  118. phydev->advertising = phydev->supported;
  119. l2sw_port->phydev = phydev;
  120. phy_config(phydev);
  121. #endif
  122. return 0;
  123. }
  124. static int vsc9953_port_init(int port_no)
  125. {
  126. struct eth_device *dev;
  127. /* Internal ports never have a PHY */
  128. if (VSC9953_INTERNAL_PORT_CHECK(port_no))
  129. return 0;
  130. /* alloc eth device */
  131. dev = (struct eth_device *)calloc(1, sizeof(struct eth_device));
  132. if (!dev)
  133. return -ENOMEM;
  134. sprintf(dev->name, "SW@PORT%d", port_no);
  135. dev->priv = &vsc9953_l2sw.port[port_no];
  136. dev->init = NULL;
  137. dev->halt = NULL;
  138. dev->send = NULL;
  139. dev->recv = NULL;
  140. if (init_phy(dev)) {
  141. free(dev);
  142. return -ENODEV;
  143. }
  144. return 0;
  145. }
  146. static int vsc9953_vlan_table_poll_idle(void)
  147. {
  148. struct vsc9953_analyzer *l2ana_reg;
  149. int timeout;
  150. l2ana_reg = (struct vsc9953_analyzer *)(VSC9953_OFFSET +
  151. VSC9953_ANA_OFFSET);
  152. timeout = 50000;
  153. while (((in_le32(&l2ana_reg->ana_tables.vlan_access) &
  154. VSC9953_VLAN_CMD_MASK) != VSC9953_VLAN_CMD_IDLE) && --timeout)
  155. udelay(1);
  156. return timeout ? 0 : -EBUSY;
  157. }
  158. /* vlan table set/clear all membership of vid */
  159. static void vsc9953_vlan_table_membership_all_set(int vid, int set_member)
  160. {
  161. uint val;
  162. struct vsc9953_analyzer *l2ana_reg;
  163. l2ana_reg = (struct vsc9953_analyzer *)(VSC9953_OFFSET +
  164. VSC9953_ANA_OFFSET);
  165. if (vsc9953_vlan_table_poll_idle() < 0) {
  166. debug("VLAN table timeout\n");
  167. return;
  168. }
  169. /* read current vlan configuration */
  170. val = in_le32(&l2ana_reg->ana_tables.vlan_tidx);
  171. out_le32(&l2ana_reg->ana_tables.vlan_tidx,
  172. bitfield_replace_by_mask(val, VSC9953_ANA_TBL_VID_MASK, vid));
  173. clrsetbits_le32(&l2ana_reg->ana_tables.vlan_access,
  174. VSC9953_VLAN_CMD_MASK, VSC9953_VLAN_CMD_READ);
  175. if (vsc9953_vlan_table_poll_idle() < 0) {
  176. debug("VLAN table timeout\n");
  177. return;
  178. }
  179. val = in_le32(&l2ana_reg->ana_tables.vlan_tidx);
  180. out_le32(&l2ana_reg->ana_tables.vlan_tidx,
  181. bitfield_replace_by_mask(val, VSC9953_ANA_TBL_VID_MASK, vid));
  182. clrsetbits_le32(&l2ana_reg->ana_tables.vlan_access,
  183. VSC9953_VLAN_PORT_MASK | VSC9953_VLAN_CMD_MASK,
  184. VSC9953_VLAN_CMD_WRITE |
  185. (set_member ? VSC9953_VLAN_PORT_MASK : 0));
  186. }
  187. /* Set PVID for a VSC9953 port */
  188. static void vsc9953_port_vlan_pvid_set(int port_no, int pvid)
  189. {
  190. uint val;
  191. struct vsc9953_analyzer *l2ana_reg;
  192. struct vsc9953_rew_reg *l2rew_reg;
  193. /* Administrative down */
  194. if (!vsc9953_l2sw.port[port_no].enabled) {
  195. printf("Port %d is administrative down\n", port_no);
  196. return;
  197. }
  198. l2ana_reg = (struct vsc9953_analyzer *)(VSC9953_OFFSET +
  199. VSC9953_ANA_OFFSET);
  200. l2rew_reg = (struct vsc9953_rew_reg *)(VSC9953_OFFSET +
  201. VSC9953_REW_OFFSET);
  202. /* Set PVID on ingress */
  203. val = in_le32(&l2ana_reg->port[port_no].vlan_cfg);
  204. val = bitfield_replace_by_mask(val, VSC9953_VLAN_CFG_VID_MASK, pvid);
  205. out_le32(&l2ana_reg->port[port_no].vlan_cfg, val);
  206. /* Set PVID on egress */
  207. val = in_le32(&l2rew_reg->port[port_no].port_vlan_cfg);
  208. val = bitfield_replace_by_mask(val, VSC9953_PORT_VLAN_CFG_VID_MASK,
  209. pvid);
  210. out_le32(&l2rew_reg->port[port_no].port_vlan_cfg, val);
  211. }
  212. static void vsc9953_port_all_vlan_pvid_set(int pvid)
  213. {
  214. int i;
  215. for (i = 0; i < VSC9953_MAX_PORTS; i++)
  216. vsc9953_port_vlan_pvid_set(i, pvid);
  217. }
  218. /* Enable/disable vlan aware of a VSC9953 port */
  219. static void vsc9953_port_vlan_aware_set(int port_no, int enabled)
  220. {
  221. struct vsc9953_analyzer *l2ana_reg;
  222. /* Administrative down */
  223. if (!vsc9953_l2sw.port[port_no].enabled) {
  224. printf("Port %d is administrative down\n", port_no);
  225. return;
  226. }
  227. l2ana_reg = (struct vsc9953_analyzer *)(VSC9953_OFFSET +
  228. VSC9953_ANA_OFFSET);
  229. if (enabled)
  230. setbits_le32(&l2ana_reg->port[port_no].vlan_cfg,
  231. VSC9953_VLAN_CFG_AWARE_ENA);
  232. else
  233. clrbits_le32(&l2ana_reg->port[port_no].vlan_cfg,
  234. VSC9953_VLAN_CFG_AWARE_ENA);
  235. }
  236. /* Set all VSC9953 ports' vlan aware */
  237. static void vsc9953_port_all_vlan_aware_set(int enabled)
  238. {
  239. int i;
  240. for (i = 0; i < VSC9953_MAX_PORTS; i++)
  241. vsc9953_port_vlan_aware_set(i, enabled);
  242. }
  243. /* Enable/disable vlan pop count of a VSC9953 port */
  244. static void vsc9953_port_vlan_popcnt_set(int port_no, int popcnt)
  245. {
  246. uint val;
  247. struct vsc9953_analyzer *l2ana_reg;
  248. /* Administrative down */
  249. if (!vsc9953_l2sw.port[port_no].enabled) {
  250. printf("Port %d is administrative down\n", port_no);
  251. return;
  252. }
  253. if (popcnt > 3 || popcnt < 0) {
  254. printf("Invalid pop count value: %d\n", port_no);
  255. return;
  256. }
  257. l2ana_reg = (struct vsc9953_analyzer *)(VSC9953_OFFSET +
  258. VSC9953_ANA_OFFSET);
  259. val = in_le32(&l2ana_reg->port[port_no].vlan_cfg);
  260. val = bitfield_replace_by_mask(val, VSC9953_VLAN_CFG_POP_CNT_MASK,
  261. popcnt);
  262. out_le32(&l2ana_reg->port[port_no].vlan_cfg, val);
  263. }
  264. /* Set all VSC9953 ports' pop count */
  265. static void vsc9953_port_all_vlan_poncnt_set(int popcnt)
  266. {
  267. int i;
  268. for (i = 0; i < VSC9953_MAX_PORTS; i++)
  269. vsc9953_port_vlan_popcnt_set(i, popcnt);
  270. }
  271. /* Enable/disable learning for frames dropped due to ingress filtering */
  272. static void vsc9953_vlan_ingr_fltr_learn_drop(int enable)
  273. {
  274. struct vsc9953_analyzer *l2ana_reg;
  275. l2ana_reg = (struct vsc9953_analyzer *)(VSC9953_OFFSET +
  276. VSC9953_ANA_OFFSET);
  277. if (enable)
  278. setbits_le32(&l2ana_reg->ana.adv_learn, VSC9953_VLAN_CHK);
  279. else
  280. clrbits_le32(&l2ana_reg->ana.adv_learn, VSC9953_VLAN_CHK);
  281. }
  282. /* Egress untag modes of a VSC9953 port */
  283. enum egress_untag_mode {
  284. EGRESS_UNTAG_ALL = 0,
  285. EGRESS_UNTAG_PVID_AND_ZERO,
  286. EGRESS_UNTAG_ZERO,
  287. EGRESS_UNTAG_NONE,
  288. };
  289. static void vsc9953_port_vlan_egr_untag_set(int port_no,
  290. enum egress_untag_mode mode)
  291. {
  292. struct vsc9953_rew_reg *l2rew_reg;
  293. /* Administrative down */
  294. if (!vsc9953_l2sw.port[port_no].enabled) {
  295. printf("Port %d is administrative down\n", port_no);
  296. return;
  297. }
  298. l2rew_reg = (struct vsc9953_rew_reg *)(VSC9953_OFFSET +
  299. VSC9953_REW_OFFSET);
  300. switch (mode) {
  301. case EGRESS_UNTAG_ALL:
  302. clrsetbits_le32(&l2rew_reg->port[port_no].port_tag_cfg,
  303. VSC9953_TAG_CFG_MASK, VSC9953_TAG_CFG_NONE);
  304. break;
  305. case EGRESS_UNTAG_PVID_AND_ZERO:
  306. clrsetbits_le32(&l2rew_reg->port[port_no].port_tag_cfg,
  307. VSC9953_TAG_CFG_MASK,
  308. VSC9953_TAG_CFG_ALL_BUT_PVID_ZERO);
  309. break;
  310. case EGRESS_UNTAG_ZERO:
  311. clrsetbits_le32(&l2rew_reg->port[port_no].port_tag_cfg,
  312. VSC9953_TAG_CFG_MASK,
  313. VSC9953_TAG_CFG_ALL_BUT_ZERO);
  314. break;
  315. case EGRESS_UNTAG_NONE:
  316. clrsetbits_le32(&l2rew_reg->port[port_no].port_tag_cfg,
  317. VSC9953_TAG_CFG_MASK, VSC9953_TAG_CFG_ALL);
  318. break;
  319. default:
  320. printf("Unknown untag mode for port %d\n", port_no);
  321. }
  322. }
  323. static void vsc9953_port_all_vlan_egress_untagged_set(
  324. enum egress_untag_mode mode)
  325. {
  326. int i;
  327. for (i = 0; i < VSC9953_MAX_PORTS; i++)
  328. vsc9953_port_vlan_egr_untag_set(i, mode);
  329. }
  330. /*****************************************************************************
  331. At startup, the default configuration would be:
  332. - HW learning enabled on all ports; (HW default)
  333. - All ports are in VLAN 1;
  334. - All ports are VLAN aware;
  335. - All ports have POP_COUNT 1;
  336. - All ports have PVID 1;
  337. - All ports have TPID 0x8100; (HW default)
  338. - All ports tag frames classified to all VLANs that are not PVID;
  339. *****************************************************************************/
  340. void vsc9953_default_configuration(void)
  341. {
  342. int i;
  343. for (i = 0; i < VSC9953_MAX_VLAN; i++)
  344. vsc9953_vlan_table_membership_all_set(i, 0);
  345. vsc9953_port_all_vlan_aware_set(1);
  346. vsc9953_port_all_vlan_pvid_set(1);
  347. vsc9953_port_all_vlan_poncnt_set(1);
  348. vsc9953_vlan_table_membership_all_set(1, 1);
  349. vsc9953_vlan_ingr_fltr_learn_drop(1);
  350. vsc9953_port_all_vlan_egress_untagged_set(EGRESS_UNTAG_PVID_AND_ZERO);
  351. }
  352. void vsc9953_init(bd_t *bis)
  353. {
  354. u32 i;
  355. u32 hdx_cfg = 0;
  356. u32 phy_addr = 0;
  357. int timeout;
  358. struct vsc9953_system_reg *l2sys_reg;
  359. struct vsc9953_qsys_reg *l2qsys_reg;
  360. struct vsc9953_dev_gmii *l2dev_gmii_reg;
  361. struct vsc9953_analyzer *l2ana_reg;
  362. struct vsc9953_devcpu_gcb *l2dev_gcb;
  363. l2dev_gmii_reg = (struct vsc9953_dev_gmii *)(VSC9953_OFFSET +
  364. VSC9953_DEV_GMII_OFFSET);
  365. l2ana_reg = (struct vsc9953_analyzer *)(VSC9953_OFFSET +
  366. VSC9953_ANA_OFFSET);
  367. l2sys_reg = (struct vsc9953_system_reg *)(VSC9953_OFFSET +
  368. VSC9953_SYS_OFFSET);
  369. l2qsys_reg = (struct vsc9953_qsys_reg *)(VSC9953_OFFSET +
  370. VSC9953_QSYS_OFFSET);
  371. l2dev_gcb = (struct vsc9953_devcpu_gcb *)(VSC9953_OFFSET +
  372. VSC9953_DEVCPU_GCB);
  373. out_le32(&l2dev_gcb->chip_regs.soft_rst,
  374. VSC9953_SOFT_SWC_RST_ENA);
  375. timeout = 50000;
  376. while ((in_le32(&l2dev_gcb->chip_regs.soft_rst) &
  377. VSC9953_SOFT_SWC_RST_ENA) && --timeout)
  378. udelay(1); /* busy wait for vsc9953 soft reset */
  379. if (timeout == 0)
  380. debug("Timeout waiting for VSC9953 to reset\n");
  381. out_le32(&l2sys_reg->sys.reset_cfg, VSC9953_MEM_ENABLE |
  382. VSC9953_MEM_INIT);
  383. timeout = 50000;
  384. while ((in_le32(&l2sys_reg->sys.reset_cfg) &
  385. VSC9953_MEM_INIT) && --timeout)
  386. udelay(1); /* busy wait for vsc9953 memory init */
  387. if (timeout == 0)
  388. debug("Timeout waiting for VSC9953 memory to initialize\n");
  389. out_le32(&l2sys_reg->sys.reset_cfg, (in_le32(&l2sys_reg->sys.reset_cfg)
  390. | VSC9953_CORE_ENABLE));
  391. /* VSC9953 Setting to be done once only */
  392. out_le32(&l2qsys_reg->sys.ext_cpu_cfg, 0x00000b00);
  393. for (i = 0; i < VSC9953_MAX_PORTS; i++) {
  394. if (vsc9953_port_init(i))
  395. printf("Failed to initialize l2switch port %d\n", i);
  396. /* Enable VSC9953 GMII Ports Port ID 0 - 7 */
  397. if (VSC9953_INTERNAL_PORT_CHECK(i)) {
  398. out_le32(&l2ana_reg->pfc[i].pfc_cfg,
  399. VSC9953_PFC_FC_QSGMII);
  400. out_le32(&l2sys_reg->pause_cfg.mac_fc_cfg[i],
  401. VSC9953_MAC_FC_CFG_QSGMII);
  402. } else {
  403. out_le32(&l2ana_reg->pfc[i].pfc_cfg,
  404. VSC9953_PFC_FC);
  405. out_le32(&l2sys_reg->pause_cfg.mac_fc_cfg[i],
  406. VSC9953_MAC_FC_CFG);
  407. }
  408. out_le32(&l2dev_gmii_reg->port_mode.clock_cfg,
  409. VSC9953_CLOCK_CFG);
  410. out_le32(&l2dev_gmii_reg->mac_cfg_status.mac_ena_cfg,
  411. VSC9953_MAC_ENA_CFG);
  412. out_le32(&l2dev_gmii_reg->mac_cfg_status.mac_mode_cfg,
  413. VSC9953_MAC_MODE_CFG);
  414. out_le32(&l2dev_gmii_reg->mac_cfg_status.mac_ifg_cfg,
  415. VSC9953_MAC_IFG_CFG);
  416. /* mac_hdx_cfg varies with port id*/
  417. hdx_cfg = VSC9953_MAC_HDX_CFG | (i << 16);
  418. out_le32(&l2dev_gmii_reg->mac_cfg_status.mac_hdx_cfg, hdx_cfg);
  419. out_le32(&l2sys_reg->sys.front_port_mode[i],
  420. VSC9953_FRONT_PORT_MODE);
  421. setbits_le32(&l2qsys_reg->sys.switch_port_mode[i],
  422. VSC9953_PORT_ENA);
  423. out_le32(&l2dev_gmii_reg->mac_cfg_status.mac_maxlen_cfg,
  424. VSC9953_MAC_MAX_LEN);
  425. out_le32(&l2sys_reg->pause_cfg.pause_cfg[i],
  426. VSC9953_PAUSE_CFG);
  427. /* WAIT FOR 2 us*/
  428. udelay(2);
  429. l2dev_gmii_reg = (struct vsc9953_dev_gmii *)(
  430. (char *)l2dev_gmii_reg
  431. + T1040_SWITCH_GMII_DEV_OFFSET);
  432. /* Initialize Lynx PHY Wrappers */
  433. phy_addr = 0;
  434. if (vsc9953_l2sw.port[i].enet_if ==
  435. PHY_INTERFACE_MODE_QSGMII)
  436. phy_addr = (i + 0x4) & 0x1F;
  437. else if (vsc9953_l2sw.port[i].enet_if ==
  438. PHY_INTERFACE_MODE_SGMII)
  439. phy_addr = (i + 1) & 0x1F;
  440. if (phy_addr) {
  441. /* SGMII IF mode + AN enable */
  442. vsc9953_mdio_write(&l2dev_gcb->mii_mng[0], phy_addr,
  443. 0x14, PHY_SGMII_IF_MODE_AN |
  444. PHY_SGMII_IF_MODE_SGMII);
  445. /* Dev ability according to SGMII specification */
  446. vsc9953_mdio_write(&l2dev_gcb->mii_mng[0], phy_addr,
  447. 0x4, PHY_SGMII_DEV_ABILITY_SGMII);
  448. /* Adjust link timer for SGMII
  449. * 1.6 ms in units of 8 ns = 2 * 10^5 = 0x30d40
  450. */
  451. vsc9953_mdio_write(&l2dev_gcb->mii_mng[0], phy_addr,
  452. 0x13, 0x0003);
  453. vsc9953_mdio_write(&l2dev_gcb->mii_mng[0], phy_addr,
  454. 0x12, 0x0d40);
  455. /* Restart AN */
  456. vsc9953_mdio_write(&l2dev_gcb->mii_mng[0], phy_addr,
  457. 0x0, PHY_SGMII_CR_DEF_VAL |
  458. PHY_SGMII_CR_RESET_AN);
  459. timeout = 50000;
  460. while ((vsc9953_mdio_read(&l2dev_gcb->mii_mng[0],
  461. phy_addr, 0x01) & 0x0020) && --timeout)
  462. udelay(1); /* wait for AN to complete */
  463. if (timeout == 0)
  464. debug("Timeout waiting for AN to complete\n");
  465. }
  466. }
  467. vsc9953_default_configuration();
  468. printf("VSC9953 L2 switch initialized\n");
  469. return;
  470. }
  471. #ifdef CONFIG_VSC9953_CMD
  472. /* Enable/disable status of a VSC9953 port */
  473. static void vsc9953_port_status_set(int port_no, u8 enabled)
  474. {
  475. struct vsc9953_qsys_reg *l2qsys_reg;
  476. /* Administrative down */
  477. if (!vsc9953_l2sw.port[port_no].enabled)
  478. return;
  479. l2qsys_reg = (struct vsc9953_qsys_reg *)(VSC9953_OFFSET +
  480. VSC9953_QSYS_OFFSET);
  481. if (enabled)
  482. setbits_le32(&l2qsys_reg->sys.switch_port_mode[port_no],
  483. VSC9953_PORT_ENA);
  484. else
  485. clrbits_le32(&l2qsys_reg->sys.switch_port_mode[port_no],
  486. VSC9953_PORT_ENA);
  487. }
  488. /* Set all VSC9953 ports' status */
  489. static void vsc9953_port_all_status_set(u8 enabled)
  490. {
  491. int i;
  492. for (i = 0; i < VSC9953_MAX_PORTS; i++)
  493. vsc9953_port_status_set(i, enabled);
  494. }
  495. /* Start autonegotiation for a VSC9953 PHY */
  496. static void vsc9953_phy_autoneg(int port_no)
  497. {
  498. if (!vsc9953_l2sw.port[port_no].phydev)
  499. return;
  500. if (vsc9953_l2sw.port[port_no].phydev->drv->startup(
  501. vsc9953_l2sw.port[port_no].phydev))
  502. printf("Failed to start PHY for port %d\n", port_no);
  503. }
  504. /* Start autonegotiation for all VSC9953 PHYs */
  505. static void vsc9953_phy_all_autoneg(void)
  506. {
  507. int i;
  508. for (i = 0; i < VSC9953_MAX_PORTS; i++)
  509. vsc9953_phy_autoneg(i);
  510. }
  511. /* Print a VSC9953 port's configuration */
  512. static void vsc9953_port_config_show(int port_no)
  513. {
  514. int speed;
  515. int duplex;
  516. int link;
  517. u8 enabled;
  518. u32 val;
  519. struct vsc9953_qsys_reg *l2qsys_reg;
  520. l2qsys_reg = (struct vsc9953_qsys_reg *)(VSC9953_OFFSET +
  521. VSC9953_QSYS_OFFSET);
  522. val = in_le32(&l2qsys_reg->sys.switch_port_mode[port_no]);
  523. enabled = vsc9953_l2sw.port[port_no].enabled &&
  524. (val & VSC9953_PORT_ENA);
  525. /* internal ports (8 and 9) are fixed */
  526. if (VSC9953_INTERNAL_PORT_CHECK(port_no)) {
  527. link = 1;
  528. speed = SPEED_2500;
  529. duplex = DUPLEX_FULL;
  530. } else {
  531. if (vsc9953_l2sw.port[port_no].phydev) {
  532. link = vsc9953_l2sw.port[port_no].phydev->link;
  533. speed = vsc9953_l2sw.port[port_no].phydev->speed;
  534. duplex = vsc9953_l2sw.port[port_no].phydev->duplex;
  535. } else {
  536. link = -1;
  537. speed = -1;
  538. duplex = -1;
  539. }
  540. }
  541. printf("%8d ", port_no);
  542. printf("%8s ", enabled == 1 ? "enabled" : "disabled");
  543. printf("%8s ", link == 1 ? "up" : "down");
  544. switch (speed) {
  545. case SPEED_10:
  546. printf("%8d ", 10);
  547. break;
  548. case SPEED_100:
  549. printf("%8d ", 100);
  550. break;
  551. case SPEED_1000:
  552. printf("%8d ", 1000);
  553. break;
  554. case SPEED_2500:
  555. printf("%8d ", 2500);
  556. break;
  557. case SPEED_10000:
  558. printf("%8d ", 10000);
  559. break;
  560. default:
  561. printf("%8s ", "-");
  562. }
  563. printf("%8s\n", duplex == DUPLEX_FULL ? "full" : "half");
  564. }
  565. /* Print VSC9953 ports' configuration */
  566. static void vsc9953_port_all_config_show(void)
  567. {
  568. int i;
  569. for (i = 0; i < VSC9953_MAX_PORTS; i++)
  570. vsc9953_port_config_show(i);
  571. }
  572. /* function to interpret commands starting with "ethsw " */
  573. static int do_ethsw(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
  574. {
  575. u8 enable;
  576. u32 port;
  577. if (argc < 4)
  578. return -1;
  579. if (strcmp(argv[1], "port"))
  580. return -1;
  581. if (!strcmp(argv[3], "show")) {
  582. if (!strcmp(argv[2], "all")) {
  583. vsc9953_phy_all_autoneg();
  584. printf("%8s %8s %8s %8s %8s\n",
  585. "Port", "Status", "Link", "Speed",
  586. "Duplex");
  587. vsc9953_port_all_config_show();
  588. return 0;
  589. } else {
  590. port = simple_strtoul(argv[2], NULL, 10);
  591. if (!VSC9953_PORT_CHECK(port))
  592. return -1;
  593. vsc9953_phy_autoneg(port);
  594. printf("%8s %8s %8s %8s %8s\n",
  595. "Port", "Status", "Link", "Speed",
  596. "Duplex");
  597. vsc9953_port_config_show(port);
  598. return 0;
  599. }
  600. } else if (!strcmp(argv[3], "enable")) {
  601. enable = 1;
  602. } else if (!strcmp(argv[3], "disable")) {
  603. enable = 0;
  604. } else {
  605. return -1;
  606. }
  607. if (!strcmp(argv[2], "all")) {
  608. vsc9953_port_all_status_set(enable);
  609. return 0;
  610. } else {
  611. port = simple_strtoul(argv[2], NULL, 10);
  612. if (!VSC9953_PORT_CHECK(port))
  613. return -1;
  614. vsc9953_port_status_set(port, enable);
  615. return 0;
  616. }
  617. return -1;
  618. }
  619. U_BOOT_CMD(ethsw, 5, 0, do_ethsw,
  620. "vsc9953 l2 switch commands",
  621. "port <port_no> enable|disable\n"
  622. " - enable/disable an l2 switch port\n"
  623. " port_no=0..9; use \"all\" for all ports\n"
  624. "ethsw port <port_no> show\n"
  625. " - show an l2 switch port's configuration\n"
  626. " port_no=0..9; use \"all\" for all ports\n"
  627. );
  628. #endif /* CONFIG_VSC9953_CMD */