servalt_switch.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526
  1. // SPDX-License-Identifier: (GPL-2.0+ OR MIT)
  2. /*
  3. * Copyright (c) 2019 Microsemi Corporation
  4. */
  5. #include <common.h>
  6. #include <config.h>
  7. #include <dm.h>
  8. #include <malloc.h>
  9. #include <dm/of_access.h>
  10. #include <dm/of_addr.h>
  11. #include <fdt_support.h>
  12. #include <linux/bitops.h>
  13. #include <linux/io.h>
  14. #include <linux/ioport.h>
  15. #include <miiphy.h>
  16. #include <net.h>
  17. #include <wait_bit.h>
  18. #include "mscc_xfer.h"
  19. #include "mscc_miim.h"
  20. #define PHY_CFG 0x0
  21. #define PHY_CFG_ENA 0x3
  22. #define PHY_CFG_COMMON_RST BIT(2)
  23. #define PHY_CFG_RST (0x3 << 3)
  24. #define PHY_STAT 0x4
  25. #define PHY_STAT_SUPERVISOR_COMPLETE BIT(0)
  26. #define ANA_AC_RAM_CTRL_RAM_INIT 0x14fdc
  27. #define ANA_AC_STAT_GLOBAL_CFG_PORT_RESET 0x15474
  28. #define ANA_CL_PORT_VLAN_CFG(x) (0xa018 + 0xc8 * (x))
  29. #define ANA_CL_PORT_VLAN_CFG_AWARE_ENA BIT(19)
  30. #define ANA_CL_PORT_VLAN_CFG_POP_CNT(x) ((x) << 17)
  31. #define ANA_L2_COMMON_FWD_CFG 0x18498
  32. #define ANA_L2_COMMON_FWD_CFG_CPU_DMAC_COPY_ENA BIT(6)
  33. #define ASM_CFG_STAT_CFG 0xb08
  34. #define ASM_CFG_PORT(x) (0xb74 + 0x4 * (x))
  35. #define ASM_CFG_PORT_NO_PREAMBLE_ENA BIT(8)
  36. #define ASM_CFG_PORT_INJ_FORMAT_CFG(x) ((x) << 1)
  37. #define ASM_RAM_CTRL_RAM_INIT 0xbfc
  38. #define DEV_DEV_CFG_DEV_RST_CTRL 0x0
  39. #define DEV_DEV_CFG_DEV_RST_CTRL_SPEED_SEL(x) ((x) << 20)
  40. #define DEV_MAC_CFG_MAC_ENA 0x24
  41. #define DEV_MAC_CFG_MAC_ENA_RX_ENA BIT(4)
  42. #define DEV_MAC_CFG_MAC_ENA_TX_ENA BIT(0)
  43. #define DEV_MAC_CFG_MAC_IFG 0x3c
  44. #define DEV_MAC_CFG_MAC_IFG_TX_IFG(x) ((x) << 8)
  45. #define DEV_MAC_CFG_MAC_IFG_RX_IFG2(x) ((x) << 4)
  46. #define DEV_MAC_CFG_MAC_IFG_RX_IFG1(x) (x)
  47. #define DEV_PCS1G_CFG_PCS1G_CFG 0x48
  48. #define DEV_PCS1G_CFG_PCS1G_CFG_PCS_ENA BIT(0)
  49. #define DEV_PCS1G_CFG_PCS1G_MODE 0x4c
  50. #define DEV_PCS1G_CFG_PCS1G_SD 0x50
  51. #define DEV_PCS1G_CFG_PCS1G_ANEG 0x54
  52. #define DEV_PCS1G_CFG_PCS1G_ANEG_ADV_ABILITY(x) ((x) << 16)
  53. #define LRN_COMMON_ACCESS_CTRL 0x0
  54. #define LRN_COMMON_ACCESS_CTRL_MAC_TABLE_ACCESS_SHOT BIT(0)
  55. #define LRN_COMMON_MAC_ACCESS_CFG0 0x4
  56. #define LRN_COMMON_MAC_ACCESS_CFG1 0x8
  57. #define LRN_COMMON_MAC_ACCESS_CFG2 0xc
  58. #define LRN_COMMON_MAC_ACCESS_CFG2_MAC_ENTRY_ADDR(x) (x)
  59. #define LRN_COMMON_MAC_ACCESS_CFG2_MAC_ENTRY_TYPE(x) ((x) << 12)
  60. #define LRN_COMMON_MAC_ACCESS_CFG2_MAC_ENTRY_VLD BIT(15)
  61. #define LRN_COMMON_MAC_ACCESS_CFG2_MAC_ENTRY_LOCKED BIT(16)
  62. #define LRN_COMMON_MAC_ACCESS_CFG2_MAC_ENTRY_CPU_COPY BIT(23)
  63. #define LRN_COMMON_MAC_ACCESS_CFG2_MAC_ENTRY_CPU_QU(x) ((x) << 24)
  64. #define QFWD_SYSTEM_SWITCH_PORT_MODE(x) (0x4400 + 0x4 * (x))
  65. #define QFWD_SYSTEM_SWITCH_PORT_MODE_PORT_ENA BIT(17)
  66. #define QS_XTR_GRP_CFG(x) (4 * (x))
  67. #define QS_INJ_GRP_CFG(x) (0x24 + (x) * 4)
  68. #define QSYS_SYSTEM_RESET_CFG 0x1048
  69. #define QSYS_CALCFG_CAL_AUTO 0x1134
  70. #define QSYS_CALCFG_CAL_CTRL 0x113c
  71. #define QSYS_CALCFG_CAL_CTRL_CAL_MODE(x) ((x) << 11)
  72. #define QSYS_RAM_CTRL_RAM_INIT 0x1140
  73. #define REW_RAM_CTRL_RAM_INIT 0xFFF4
  74. #define MAC_VID 0
  75. #define CPU_PORT 11
  76. #define IFH_LEN 7
  77. #define ETH_ALEN 6
  78. #define PGID_BROADCAST 50
  79. #define PGID_UNICAST 51
  80. static const char * const regs_names[] = {
  81. "port0", "port1",
  82. "ana_ac", "ana_cl", "ana_l2", "asm", "lrn", "qfwd", "qs", "qsys", "rew",
  83. };
  84. #define REGS_NAMES_COUNT ARRAY_SIZE(regs_names) + 1
  85. #define MAX_PORT 2
  86. enum servalt_ctrl_regs {
  87. ANA_AC = MAX_PORT,
  88. ANA_CL,
  89. ANA_L2,
  90. ASM,
  91. LRN,
  92. QFWD,
  93. QS,
  94. QSYS,
  95. REW,
  96. };
  97. #define SERVALT_MIIM_BUS_COUNT 2
  98. struct servalt_phy_port_t {
  99. size_t phy_addr;
  100. struct mii_dev *bus;
  101. };
  102. struct servalt_private {
  103. void __iomem *regs[REGS_NAMES_COUNT];
  104. struct mii_dev *bus[SERVALT_MIIM_BUS_COUNT];
  105. struct servalt_phy_port_t ports[MAX_PORT];
  106. };
  107. static const unsigned long servalt_regs_qs[] = {
  108. [MSCC_QS_XTR_RD] = 0x8,
  109. [MSCC_QS_XTR_FLUSH] = 0x18,
  110. [MSCC_QS_XTR_DATA_PRESENT] = 0x1c,
  111. [MSCC_QS_INJ_WR] = 0x2c,
  112. [MSCC_QS_INJ_CTRL] = 0x34,
  113. };
  114. static struct mscc_miim_dev miim[SERVALT_MIIM_BUS_COUNT];
  115. static int miim_count = -1;
  116. static void mscc_phy_reset(void)
  117. {
  118. writel(0, BASE_DEVCPU_GCB + GCB_PHY_CFG + PHY_CFG);
  119. writel(PHY_CFG_RST | PHY_CFG_COMMON_RST
  120. | PHY_CFG_ENA, BASE_DEVCPU_GCB + GCB_PHY_CFG + PHY_CFG);
  121. if (wait_for_bit_le32((const void *)(BASE_DEVCPU_GCB + GCB_PHY_CFG) +
  122. PHY_STAT, PHY_STAT_SUPERVISOR_COMPLETE,
  123. true, 2000, false)) {
  124. pr_err("Timeout in phy reset\n");
  125. }
  126. }
  127. static void servalt_cpu_capture_setup(struct servalt_private *priv)
  128. {
  129. /* ASM: No preamble and IFH prefix on CPU injected frames */
  130. writel(ASM_CFG_PORT_NO_PREAMBLE_ENA |
  131. ASM_CFG_PORT_INJ_FORMAT_CFG(1),
  132. priv->regs[ASM] + ASM_CFG_PORT(CPU_PORT));
  133. /* Set Manual injection via DEVCPU_QS registers for CPU queue 0 */
  134. writel(0x5, priv->regs[QS] + QS_INJ_GRP_CFG(0));
  135. /* Set Manual extraction via DEVCPU_QS registers for CPU queue 0 */
  136. writel(0x7, priv->regs[QS] + QS_XTR_GRP_CFG(0));
  137. /* Enable CPU port for any frame transfer */
  138. setbits_le32(priv->regs[QFWD] + QFWD_SYSTEM_SWITCH_PORT_MODE(CPU_PORT),
  139. QFWD_SYSTEM_SWITCH_PORT_MODE_PORT_ENA);
  140. /* Send a copy to CPU when found as forwarding entry */
  141. setbits_le32(priv->regs[ANA_L2] + ANA_L2_COMMON_FWD_CFG,
  142. ANA_L2_COMMON_FWD_CFG_CPU_DMAC_COPY_ENA);
  143. }
  144. static void servalt_port_init(struct servalt_private *priv, int port)
  145. {
  146. void __iomem *regs = priv->regs[port];
  147. /* Enable PCS */
  148. writel(DEV_PCS1G_CFG_PCS1G_CFG_PCS_ENA,
  149. regs + DEV_PCS1G_CFG_PCS1G_CFG);
  150. /* Disable Signal Detect */
  151. writel(0, regs + DEV_PCS1G_CFG_PCS1G_SD);
  152. /* Enable MAC RX and TX */
  153. writel(DEV_MAC_CFG_MAC_ENA_RX_ENA |
  154. DEV_MAC_CFG_MAC_ENA_TX_ENA,
  155. regs + DEV_MAC_CFG_MAC_ENA);
  156. /* Clear sgmii_mode_ena */
  157. writel(0, regs + DEV_PCS1G_CFG_PCS1G_MODE);
  158. /*
  159. * Clear sw_resolve_ena(bit 0) and set adv_ability to
  160. * something meaningful just in case
  161. */
  162. writel(DEV_PCS1G_CFG_PCS1G_ANEG_ADV_ABILITY(0x20),
  163. regs + DEV_PCS1G_CFG_PCS1G_ANEG);
  164. /* Set MAC IFG Gaps */
  165. writel(DEV_MAC_CFG_MAC_IFG_TX_IFG(4) |
  166. DEV_MAC_CFG_MAC_IFG_RX_IFG1(5) |
  167. DEV_MAC_CFG_MAC_IFG_RX_IFG2(1),
  168. regs + DEV_MAC_CFG_MAC_IFG);
  169. /* Set link speed and release all resets */
  170. writel(DEV_DEV_CFG_DEV_RST_CTRL_SPEED_SEL(2),
  171. regs + DEV_DEV_CFG_DEV_RST_CTRL);
  172. /* Make VLAN aware for CPU traffic */
  173. writel(ANA_CL_PORT_VLAN_CFG_AWARE_ENA |
  174. ANA_CL_PORT_VLAN_CFG_POP_CNT(1) |
  175. MAC_VID,
  176. priv->regs[ANA_CL] + ANA_CL_PORT_VLAN_CFG(port));
  177. /* Enable CPU port for any frame transfer */
  178. setbits_le32(priv->regs[QFWD] + QFWD_SYSTEM_SWITCH_PORT_MODE(port),
  179. QFWD_SYSTEM_SWITCH_PORT_MODE_PORT_ENA);
  180. }
  181. static int ram_init(u32 val, void __iomem *addr)
  182. {
  183. writel(val, addr);
  184. if (wait_for_bit_le32(addr, BIT(1), false, 2000, false)) {
  185. printf("Timeout in memory reset, reg = 0x%08x\n", val);
  186. return 1;
  187. }
  188. return 0;
  189. }
  190. static int servalt_switch_init(struct servalt_private *priv)
  191. {
  192. /* Initialize memories */
  193. ram_init(0x3, priv->regs[QSYS] + QSYS_RAM_CTRL_RAM_INIT);
  194. ram_init(0x3, priv->regs[ASM] + ASM_RAM_CTRL_RAM_INIT);
  195. ram_init(0x3, priv->regs[ANA_AC] + ANA_AC_RAM_CTRL_RAM_INIT);
  196. ram_init(0x3, priv->regs[REW] + REW_RAM_CTRL_RAM_INIT);
  197. /* Reset counters */
  198. writel(0x1, priv->regs[ANA_AC] + ANA_AC_STAT_GLOBAL_CFG_PORT_RESET);
  199. writel(0x1, priv->regs[ASM] + ASM_CFG_STAT_CFG);
  200. /* Enable switch-core and queue system */
  201. writel(0x1, priv->regs[QSYS] + QSYS_SYSTEM_RESET_CFG);
  202. return 0;
  203. }
  204. static void servalt_switch_config(struct servalt_private *priv)
  205. {
  206. writel(0x55555555, priv->regs[QSYS] + QSYS_CALCFG_CAL_AUTO);
  207. writel(readl(priv->regs[QSYS] + QSYS_CALCFG_CAL_CTRL) |
  208. QSYS_CALCFG_CAL_CTRL_CAL_MODE(8),
  209. priv->regs[QSYS] + QSYS_CALCFG_CAL_CTRL);
  210. }
  211. static int servalt_initialize(struct servalt_private *priv)
  212. {
  213. int ret, i;
  214. /* Initialize switch memories, enable core */
  215. ret = servalt_switch_init(priv);
  216. if (ret)
  217. return ret;
  218. servalt_switch_config(priv);
  219. for (i = 0; i < MAX_PORT; i++)
  220. servalt_port_init(priv, i);
  221. servalt_cpu_capture_setup(priv);
  222. return 0;
  223. }
  224. static inline
  225. int servalt_vlant_wait_for_completion(struct servalt_private *priv)
  226. {
  227. if (wait_for_bit_le32(priv->regs[LRN] + LRN_COMMON_ACCESS_CTRL,
  228. LRN_COMMON_ACCESS_CTRL_MAC_TABLE_ACCESS_SHOT,
  229. false, 2000, false))
  230. return -ETIMEDOUT;
  231. return 0;
  232. }
  233. static int servalt_mac_table_add(struct servalt_private *priv,
  234. const unsigned char mac[ETH_ALEN], int pgid)
  235. {
  236. u32 macl = 0, mach = 0;
  237. /*
  238. * Set the MAC address to handle and the vlan associated in a format
  239. * understood by the hardware.
  240. */
  241. mach |= MAC_VID << 16;
  242. mach |= ((u32)mac[0]) << 8;
  243. mach |= ((u32)mac[1]) << 0;
  244. macl |= ((u32)mac[2]) << 24;
  245. macl |= ((u32)mac[3]) << 16;
  246. macl |= ((u32)mac[4]) << 8;
  247. macl |= ((u32)mac[5]) << 0;
  248. writel(mach, priv->regs[LRN] + LRN_COMMON_MAC_ACCESS_CFG0);
  249. writel(macl, priv->regs[LRN] + LRN_COMMON_MAC_ACCESS_CFG1);
  250. writel(LRN_COMMON_MAC_ACCESS_CFG2_MAC_ENTRY_ADDR(pgid) |
  251. LRN_COMMON_MAC_ACCESS_CFG2_MAC_ENTRY_TYPE(0x3) |
  252. LRN_COMMON_MAC_ACCESS_CFG2_MAC_ENTRY_CPU_COPY |
  253. LRN_COMMON_MAC_ACCESS_CFG2_MAC_ENTRY_CPU_QU(0) |
  254. LRN_COMMON_MAC_ACCESS_CFG2_MAC_ENTRY_VLD |
  255. LRN_COMMON_MAC_ACCESS_CFG2_MAC_ENTRY_LOCKED,
  256. priv->regs[LRN] + LRN_COMMON_MAC_ACCESS_CFG2);
  257. writel(LRN_COMMON_ACCESS_CTRL_MAC_TABLE_ACCESS_SHOT,
  258. priv->regs[LRN] + LRN_COMMON_ACCESS_CTRL);
  259. return servalt_vlant_wait_for_completion(priv);
  260. }
  261. static int servalt_write_hwaddr(struct udevice *dev)
  262. {
  263. struct servalt_private *priv = dev_get_priv(dev);
  264. struct eth_pdata *pdata = dev_get_plat(dev);
  265. return servalt_mac_table_add(priv, pdata->enetaddr, PGID_UNICAST);
  266. }
  267. static int servalt_start(struct udevice *dev)
  268. {
  269. struct servalt_private *priv = dev_get_priv(dev);
  270. struct eth_pdata *pdata = dev_get_plat(dev);
  271. const unsigned char mac[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff,
  272. 0xff };
  273. int ret;
  274. ret = servalt_initialize(priv);
  275. if (ret)
  276. return ret;
  277. /* Set MAC address tables entries for CPU redirection */
  278. ret = servalt_mac_table_add(priv, mac, PGID_BROADCAST);
  279. if (ret)
  280. return ret;
  281. ret = servalt_mac_table_add(priv, pdata->enetaddr, PGID_UNICAST);
  282. if (ret)
  283. return ret;
  284. return 0;
  285. }
  286. static void servalt_stop(struct udevice *dev)
  287. {
  288. }
  289. static int servalt_send(struct udevice *dev, void *packet, int length)
  290. {
  291. struct servalt_private *priv = dev_get_priv(dev);
  292. u32 ifh[IFH_LEN];
  293. u32 *buf = packet;
  294. memset(ifh, '\0', IFH_LEN * 4);
  295. /* Set DST PORT_MASK */
  296. ifh[0] = htonl(0);
  297. ifh[1] = htonl(0x1FFFFF);
  298. ifh[2] = htonl(~0);
  299. /* Set DST_MODE to INJECT and UPDATE_FCS */
  300. ifh[5] = htonl(0x4c0);
  301. return mscc_send(priv->regs[QS], servalt_regs_qs,
  302. ifh, IFH_LEN, buf, length);
  303. }
  304. static int servalt_recv(struct udevice *dev, int flags, uchar **packetp)
  305. {
  306. struct servalt_private *priv = dev_get_priv(dev);
  307. u32 *rxbuf = (u32 *)net_rx_packets[0];
  308. int byte_cnt = 0;
  309. byte_cnt = mscc_recv(priv->regs[QS], servalt_regs_qs, rxbuf, IFH_LEN,
  310. false);
  311. *packetp = net_rx_packets[0];
  312. return byte_cnt;
  313. }
  314. static struct mii_dev *get_mdiobus(phys_addr_t base, unsigned long size)
  315. {
  316. int i = 0;
  317. for (i = 0; i < SERVALT_MIIM_BUS_COUNT; ++i)
  318. if (miim[i].miim_base == base && miim[i].miim_size == size)
  319. return miim[i].bus;
  320. return NULL;
  321. }
  322. static void add_port_entry(struct servalt_private *priv, size_t index,
  323. size_t phy_addr, struct mii_dev *bus)
  324. {
  325. priv->ports[index].phy_addr = phy_addr;
  326. priv->ports[index].bus = bus;
  327. }
  328. static int servalt_probe(struct udevice *dev)
  329. {
  330. struct servalt_private *priv = dev_get_priv(dev);
  331. int i;
  332. struct resource res;
  333. phys_addr_t addr_base;
  334. unsigned long addr_size;
  335. ofnode eth_node, node, mdio_node;
  336. size_t phy_addr;
  337. struct mii_dev *bus;
  338. struct ofnode_phandle_args phandle;
  339. if (!priv)
  340. return -EINVAL;
  341. /* Get registers and map them to the private structure */
  342. for (i = 0; i < ARRAY_SIZE(regs_names); i++) {
  343. priv->regs[i] = dev_remap_addr_name(dev, regs_names[i]);
  344. if (!priv->regs[i]) {
  345. debug
  346. ("Error can't get regs base addresses for %s\n",
  347. regs_names[i]);
  348. return -ENOMEM;
  349. }
  350. }
  351. /* Initialize miim buses */
  352. memset(&miim, 0x0, sizeof(struct mscc_miim_dev) *
  353. SERVALT_MIIM_BUS_COUNT);
  354. /* iterate all the ports and find out on which bus they are */
  355. i = 0;
  356. eth_node = dev_read_first_subnode(dev);
  357. for (node = ofnode_first_subnode(eth_node);
  358. ofnode_valid(node);
  359. node = ofnode_next_subnode(node)) {
  360. if (ofnode_read_resource(node, 0, &res))
  361. return -ENOMEM;
  362. i = res.start;
  363. ofnode_parse_phandle_with_args(node, "phy-handle", NULL, 0, 0,
  364. &phandle);
  365. /* Get phy address on mdio bus */
  366. if (ofnode_read_resource(phandle.node, 0, &res))
  367. return -ENOMEM;
  368. phy_addr = res.start;
  369. /* Get mdio node */
  370. mdio_node = ofnode_get_parent(phandle.node);
  371. if (ofnode_read_resource(mdio_node, 0, &res))
  372. return -ENOMEM;
  373. addr_base = res.start;
  374. addr_size = res.end - res.start;
  375. /* If the bus is new then create a new bus */
  376. if (!get_mdiobus(addr_base, addr_size))
  377. priv->bus[miim_count] =
  378. mscc_mdiobus_init(miim, &miim_count, addr_base,
  379. addr_size);
  380. /* Connect mdio bus with the port */
  381. bus = get_mdiobus(addr_base, addr_size);
  382. add_port_entry(priv, i, phy_addr, bus);
  383. }
  384. mscc_phy_reset();
  385. for (i = 0; i < MAX_PORT; i++) {
  386. if (!priv->ports[i].bus)
  387. continue;
  388. phy_connect(priv->ports[i].bus, priv->ports[i].phy_addr, dev,
  389. PHY_INTERFACE_MODE_NA);
  390. }
  391. return 0;
  392. }
  393. static int servalt_remove(struct udevice *dev)
  394. {
  395. struct servalt_private *priv = dev_get_priv(dev);
  396. int i;
  397. for (i = 0; i < SERVALT_MIIM_BUS_COUNT; i++) {
  398. mdio_unregister(priv->bus[i]);
  399. mdio_free(priv->bus[i]);
  400. }
  401. return 0;
  402. }
  403. static const struct eth_ops servalt_ops = {
  404. .start = servalt_start,
  405. .stop = servalt_stop,
  406. .send = servalt_send,
  407. .recv = servalt_recv,
  408. .write_hwaddr = servalt_write_hwaddr,
  409. };
  410. static const struct udevice_id mscc_servalt_ids[] = {
  411. {.compatible = "mscc,vsc7437-switch" },
  412. { /* Sentinel */ }
  413. };
  414. U_BOOT_DRIVER(servalt) = {
  415. .name = "servalt-switch",
  416. .id = UCLASS_ETH,
  417. .of_match = mscc_servalt_ids,
  418. .probe = servalt_probe,
  419. .remove = servalt_remove,
  420. .ops = &servalt_ops,
  421. .priv_auto = sizeof(struct servalt_private),
  422. .plat_auto = sizeof(struct eth_pdata),
  423. };