rzn1_a5psw.c 34 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Copyright (C) 2022 Schneider-Electric
  4. *
  5. * Clément Léger <clement.leger@bootlin.com>
  6. */
  7. #include <linux/clk.h>
  8. #include <linux/etherdevice.h>
  9. #include <linux/if_bridge.h>
  10. #include <linux/if_ether.h>
  11. #include <linux/kernel.h>
  12. #include <linux/module.h>
  13. #include <linux/of.h>
  14. #include <linux/of_mdio.h>
  15. #include <net/dsa.h>
  16. #include "rzn1_a5psw.h"
  17. struct a5psw_stats {
  18. u16 offset;
  19. const char name[ETH_GSTRING_LEN];
  20. };
  21. #define STAT_DESC(_offset) { \
  22. .offset = A5PSW_##_offset, \
  23. .name = __stringify(_offset), \
  24. }
  25. static const struct a5psw_stats a5psw_stats[] = {
  26. STAT_DESC(aFramesTransmittedOK),
  27. STAT_DESC(aFramesReceivedOK),
  28. STAT_DESC(aFrameCheckSequenceErrors),
  29. STAT_DESC(aAlignmentErrors),
  30. STAT_DESC(aOctetsTransmittedOK),
  31. STAT_DESC(aOctetsReceivedOK),
  32. STAT_DESC(aTxPAUSEMACCtrlFrames),
  33. STAT_DESC(aRxPAUSEMACCtrlFrames),
  34. STAT_DESC(ifInErrors),
  35. STAT_DESC(ifOutErrors),
  36. STAT_DESC(ifInUcastPkts),
  37. STAT_DESC(ifInMulticastPkts),
  38. STAT_DESC(ifInBroadcastPkts),
  39. STAT_DESC(ifOutDiscards),
  40. STAT_DESC(ifOutUcastPkts),
  41. STAT_DESC(ifOutMulticastPkts),
  42. STAT_DESC(ifOutBroadcastPkts),
  43. STAT_DESC(etherStatsDropEvents),
  44. STAT_DESC(etherStatsOctets),
  45. STAT_DESC(etherStatsPkts),
  46. STAT_DESC(etherStatsUndersizePkts),
  47. STAT_DESC(etherStatsOversizePkts),
  48. STAT_DESC(etherStatsPkts64Octets),
  49. STAT_DESC(etherStatsPkts65to127Octets),
  50. STAT_DESC(etherStatsPkts128to255Octets),
  51. STAT_DESC(etherStatsPkts256to511Octets),
  52. STAT_DESC(etherStatsPkts1024to1518Octets),
  53. STAT_DESC(etherStatsPkts1519toXOctets),
  54. STAT_DESC(etherStatsJabbers),
  55. STAT_DESC(etherStatsFragments),
  56. STAT_DESC(VLANReceived),
  57. STAT_DESC(VLANTransmitted),
  58. STAT_DESC(aDeferred),
  59. STAT_DESC(aMultipleCollisions),
  60. STAT_DESC(aSingleCollisions),
  61. STAT_DESC(aLateCollisions),
  62. STAT_DESC(aExcessiveCollisions),
  63. STAT_DESC(aCarrierSenseErrors),
  64. };
  65. static void a5psw_reg_writel(struct a5psw *a5psw, int offset, u32 value)
  66. {
  67. writel(value, a5psw->base + offset);
  68. }
  69. static u32 a5psw_reg_readl(struct a5psw *a5psw, int offset)
  70. {
  71. return readl(a5psw->base + offset);
  72. }
  73. static void a5psw_reg_rmw(struct a5psw *a5psw, int offset, u32 mask, u32 val)
  74. {
  75. u32 reg;
  76. spin_lock(&a5psw->reg_lock);
  77. reg = a5psw_reg_readl(a5psw, offset);
  78. reg &= ~mask;
  79. reg |= val;
  80. a5psw_reg_writel(a5psw, offset, reg);
  81. spin_unlock(&a5psw->reg_lock);
  82. }
  83. static enum dsa_tag_protocol a5psw_get_tag_protocol(struct dsa_switch *ds,
  84. int port,
  85. enum dsa_tag_protocol mp)
  86. {
  87. return DSA_TAG_PROTO_RZN1_A5PSW;
  88. }
  89. static void a5psw_port_pattern_set(struct a5psw *a5psw, int port, int pattern,
  90. bool enable)
  91. {
  92. u32 rx_match = 0;
  93. if (enable)
  94. rx_match |= A5PSW_RXMATCH_CONFIG_PATTERN(pattern);
  95. a5psw_reg_rmw(a5psw, A5PSW_RXMATCH_CONFIG(port),
  96. A5PSW_RXMATCH_CONFIG_PATTERN(pattern), rx_match);
  97. }
  98. static void a5psw_port_mgmtfwd_set(struct a5psw *a5psw, int port, bool enable)
  99. {
  100. /* Enable "management forward" pattern matching, this will forward
  101. * packets from this port only towards the management port and thus
  102. * isolate the port.
  103. */
  104. a5psw_port_pattern_set(a5psw, port, A5PSW_PATTERN_MGMTFWD, enable);
  105. }
  106. static void a5psw_port_tx_enable(struct a5psw *a5psw, int port, bool enable)
  107. {
  108. u32 mask = A5PSW_PORT_ENA_TX(port);
  109. u32 reg = enable ? mask : 0;
  110. /* Even though the port TX is disabled through TXENA bit in the
  111. * PORT_ENA register, it can still send BPDUs. This depends on the tag
  112. * configuration added when sending packets from the CPU port to the
  113. * switch port. Indeed, when using forced forwarding without filtering,
  114. * even disabled ports will be able to send packets that are tagged.
  115. * This allows to implement STP support when ports are in a state where
  116. * forwarding traffic should be stopped but BPDUs should still be sent.
  117. */
  118. a5psw_reg_rmw(a5psw, A5PSW_PORT_ENA, mask, reg);
  119. }
  120. static void a5psw_port_enable_set(struct a5psw *a5psw, int port, bool enable)
  121. {
  122. u32 port_ena = 0;
  123. if (enable)
  124. port_ena |= A5PSW_PORT_ENA_TX_RX(port);
  125. a5psw_reg_rmw(a5psw, A5PSW_PORT_ENA, A5PSW_PORT_ENA_TX_RX(port),
  126. port_ena);
  127. }
  128. static int a5psw_lk_execute_ctrl(struct a5psw *a5psw, u32 *ctrl)
  129. {
  130. int ret;
  131. a5psw_reg_writel(a5psw, A5PSW_LK_ADDR_CTRL, *ctrl);
  132. ret = readl_poll_timeout(a5psw->base + A5PSW_LK_ADDR_CTRL, *ctrl,
  133. !(*ctrl & A5PSW_LK_ADDR_CTRL_BUSY),
  134. A5PSW_LK_BUSY_USEC_POLL, A5PSW_CTRL_TIMEOUT);
  135. if (ret)
  136. dev_err(a5psw->dev, "LK_CTRL timeout waiting for BUSY bit\n");
  137. return ret;
  138. }
  139. static void a5psw_port_fdb_flush(struct a5psw *a5psw, int port)
  140. {
  141. u32 ctrl = A5PSW_LK_ADDR_CTRL_DELETE_PORT | BIT(port);
  142. mutex_lock(&a5psw->lk_lock);
  143. a5psw_lk_execute_ctrl(a5psw, &ctrl);
  144. mutex_unlock(&a5psw->lk_lock);
  145. }
  146. static void a5psw_port_authorize_set(struct a5psw *a5psw, int port,
  147. bool authorize)
  148. {
  149. u32 reg = a5psw_reg_readl(a5psw, A5PSW_AUTH_PORT(port));
  150. if (authorize)
  151. reg |= A5PSW_AUTH_PORT_AUTHORIZED;
  152. else
  153. reg &= ~A5PSW_AUTH_PORT_AUTHORIZED;
  154. a5psw_reg_writel(a5psw, A5PSW_AUTH_PORT(port), reg);
  155. }
  156. static void a5psw_port_disable(struct dsa_switch *ds, int port)
  157. {
  158. struct a5psw *a5psw = ds->priv;
  159. a5psw_port_authorize_set(a5psw, port, false);
  160. a5psw_port_enable_set(a5psw, port, false);
  161. }
  162. static int a5psw_port_enable(struct dsa_switch *ds, int port,
  163. struct phy_device *phy)
  164. {
  165. struct a5psw *a5psw = ds->priv;
  166. a5psw_port_authorize_set(a5psw, port, true);
  167. a5psw_port_enable_set(a5psw, port, true);
  168. return 0;
  169. }
  170. static int a5psw_port_change_mtu(struct dsa_switch *ds, int port, int new_mtu)
  171. {
  172. struct a5psw *a5psw = ds->priv;
  173. new_mtu += ETH_HLEN + A5PSW_EXTRA_MTU_LEN + ETH_FCS_LEN;
  174. a5psw_reg_writel(a5psw, A5PSW_FRM_LENGTH(port), new_mtu);
  175. return 0;
  176. }
  177. static int a5psw_port_max_mtu(struct dsa_switch *ds, int port)
  178. {
  179. return A5PSW_MAX_MTU;
  180. }
  181. static void a5psw_phylink_get_caps(struct dsa_switch *ds, int port,
  182. struct phylink_config *config)
  183. {
  184. unsigned long *intf = config->supported_interfaces;
  185. config->mac_capabilities = MAC_1000FD;
  186. if (dsa_is_cpu_port(ds, port)) {
  187. /* GMII is used internally and GMAC2 is connected to the switch
  188. * using 1000Mbps Full-Duplex mode only (cf ethernet manual)
  189. */
  190. __set_bit(PHY_INTERFACE_MODE_GMII, intf);
  191. } else {
  192. config->mac_capabilities |= MAC_100 | MAC_10;
  193. phy_interface_set_rgmii(intf);
  194. __set_bit(PHY_INTERFACE_MODE_RMII, intf);
  195. __set_bit(PHY_INTERFACE_MODE_MII, intf);
  196. }
  197. }
  198. static struct phylink_pcs *
  199. a5psw_phylink_mac_select_pcs(struct phylink_config *config,
  200. phy_interface_t interface)
  201. {
  202. struct dsa_port *dp = dsa_phylink_to_port(config);
  203. struct a5psw *a5psw = dp->ds->priv;
  204. if (dsa_port_is_cpu(dp))
  205. return NULL;
  206. return a5psw->pcs[dp->index];
  207. }
  208. static void a5psw_phylink_mac_config(struct phylink_config *config,
  209. unsigned int mode,
  210. const struct phylink_link_state *state)
  211. {
  212. }
  213. static void a5psw_phylink_mac_link_down(struct phylink_config *config,
  214. unsigned int mode,
  215. phy_interface_t interface)
  216. {
  217. struct dsa_port *dp = dsa_phylink_to_port(config);
  218. struct a5psw *a5psw = dp->ds->priv;
  219. int port = dp->index;
  220. u32 cmd_cfg;
  221. cmd_cfg = a5psw_reg_readl(a5psw, A5PSW_CMD_CFG(port));
  222. cmd_cfg &= ~(A5PSW_CMD_CFG_RX_ENA | A5PSW_CMD_CFG_TX_ENA);
  223. a5psw_reg_writel(a5psw, A5PSW_CMD_CFG(port), cmd_cfg);
  224. }
  225. static void a5psw_phylink_mac_link_up(struct phylink_config *config,
  226. struct phy_device *phydev,
  227. unsigned int mode,
  228. phy_interface_t interface,
  229. int speed, int duplex, bool tx_pause,
  230. bool rx_pause)
  231. {
  232. u32 cmd_cfg = A5PSW_CMD_CFG_RX_ENA | A5PSW_CMD_CFG_TX_ENA |
  233. A5PSW_CMD_CFG_TX_CRC_APPEND;
  234. struct dsa_port *dp = dsa_phylink_to_port(config);
  235. struct a5psw *a5psw = dp->ds->priv;
  236. if (speed == SPEED_1000)
  237. cmd_cfg |= A5PSW_CMD_CFG_ETH_SPEED;
  238. if (duplex == DUPLEX_HALF)
  239. cmd_cfg |= A5PSW_CMD_CFG_HD_ENA;
  240. cmd_cfg |= A5PSW_CMD_CFG_CNTL_FRM_ENA;
  241. if (!rx_pause)
  242. cmd_cfg &= ~A5PSW_CMD_CFG_PAUSE_IGNORE;
  243. a5psw_reg_writel(a5psw, A5PSW_CMD_CFG(dp->index), cmd_cfg);
  244. }
  245. static int a5psw_set_ageing_time(struct dsa_switch *ds, unsigned int msecs)
  246. {
  247. struct a5psw *a5psw = ds->priv;
  248. unsigned long rate;
  249. u64 max, tmp;
  250. u32 agetime;
  251. rate = clk_get_rate(a5psw->clk);
  252. max = div64_ul(((u64)A5PSW_LK_AGETIME_MASK * A5PSW_TABLE_ENTRIES * 1024),
  253. rate) * 1000;
  254. if (msecs > max)
  255. return -EINVAL;
  256. tmp = div_u64(rate, MSEC_PER_SEC);
  257. agetime = div_u64(msecs * tmp, 1024 * A5PSW_TABLE_ENTRIES);
  258. a5psw_reg_writel(a5psw, A5PSW_LK_AGETIME, agetime);
  259. return 0;
  260. }
  261. static void a5psw_port_learning_set(struct a5psw *a5psw, int port, bool learn)
  262. {
  263. u32 mask = A5PSW_INPUT_LEARN_DIS(port);
  264. u32 reg = !learn ? mask : 0;
  265. a5psw_reg_rmw(a5psw, A5PSW_INPUT_LEARN, mask, reg);
  266. }
  267. static void a5psw_port_rx_block_set(struct a5psw *a5psw, int port, bool block)
  268. {
  269. u32 mask = A5PSW_INPUT_LEARN_BLOCK(port);
  270. u32 reg = block ? mask : 0;
  271. a5psw_reg_rmw(a5psw, A5PSW_INPUT_LEARN, mask, reg);
  272. }
  273. static void a5psw_flooding_set_resolution(struct a5psw *a5psw, int port,
  274. bool set)
  275. {
  276. static const u8 offsets[] = {
  277. A5PSW_UCAST_DEF_MASK, A5PSW_BCAST_DEF_MASK, A5PSW_MCAST_DEF_MASK
  278. };
  279. int i;
  280. for (i = 0; i < ARRAY_SIZE(offsets); i++)
  281. a5psw_reg_rmw(a5psw, offsets[i], BIT(port),
  282. set ? BIT(port) : 0);
  283. }
  284. static void a5psw_port_set_standalone(struct a5psw *a5psw, int port,
  285. bool standalone)
  286. {
  287. a5psw_port_learning_set(a5psw, port, !standalone);
  288. a5psw_flooding_set_resolution(a5psw, port, !standalone);
  289. a5psw_port_mgmtfwd_set(a5psw, port, standalone);
  290. }
  291. static int a5psw_port_bridge_join(struct dsa_switch *ds, int port,
  292. struct dsa_bridge bridge,
  293. bool *tx_fwd_offload,
  294. struct netlink_ext_ack *extack)
  295. {
  296. struct a5psw *a5psw = ds->priv;
  297. /* We only support 1 bridge device */
  298. if (a5psw->br_dev && bridge.dev != a5psw->br_dev) {
  299. NL_SET_ERR_MSG_MOD(extack,
  300. "Forwarding offload supported for a single bridge");
  301. return -EOPNOTSUPP;
  302. }
  303. a5psw->br_dev = bridge.dev;
  304. a5psw_port_set_standalone(a5psw, port, false);
  305. a5psw->bridged_ports |= BIT(port);
  306. return 0;
  307. }
  308. static void a5psw_port_bridge_leave(struct dsa_switch *ds, int port,
  309. struct dsa_bridge bridge)
  310. {
  311. struct a5psw *a5psw = ds->priv;
  312. a5psw->bridged_ports &= ~BIT(port);
  313. a5psw_port_set_standalone(a5psw, port, true);
  314. /* No more ports bridged */
  315. if (a5psw->bridged_ports == BIT(A5PSW_CPU_PORT))
  316. a5psw->br_dev = NULL;
  317. }
  318. static int a5psw_port_pre_bridge_flags(struct dsa_switch *ds, int port,
  319. struct switchdev_brport_flags flags,
  320. struct netlink_ext_ack *extack)
  321. {
  322. if (flags.mask & ~(BR_LEARNING | BR_FLOOD | BR_MCAST_FLOOD |
  323. BR_BCAST_FLOOD))
  324. return -EINVAL;
  325. return 0;
  326. }
  327. static int
  328. a5psw_port_bridge_flags(struct dsa_switch *ds, int port,
  329. struct switchdev_brport_flags flags,
  330. struct netlink_ext_ack *extack)
  331. {
  332. struct a5psw *a5psw = ds->priv;
  333. u32 val;
  334. /* If a port is set as standalone, we do not want to be able to
  335. * configure flooding nor learning which would result in joining the
  336. * unique bridge. This can happen when a port leaves the bridge, in
  337. * which case the DSA core will try to "clear" all flags for the
  338. * standalone port (ie enable flooding, disable learning). In that case
  339. * do not fail but do not apply the flags.
  340. */
  341. if (!(a5psw->bridged_ports & BIT(port)))
  342. return 0;
  343. if (flags.mask & BR_LEARNING) {
  344. val = flags.val & BR_LEARNING ? 0 : A5PSW_INPUT_LEARN_DIS(port);
  345. a5psw_reg_rmw(a5psw, A5PSW_INPUT_LEARN,
  346. A5PSW_INPUT_LEARN_DIS(port), val);
  347. }
  348. if (flags.mask & BR_FLOOD) {
  349. val = flags.val & BR_FLOOD ? BIT(port) : 0;
  350. a5psw_reg_rmw(a5psw, A5PSW_UCAST_DEF_MASK, BIT(port), val);
  351. }
  352. if (flags.mask & BR_MCAST_FLOOD) {
  353. val = flags.val & BR_MCAST_FLOOD ? BIT(port) : 0;
  354. a5psw_reg_rmw(a5psw, A5PSW_MCAST_DEF_MASK, BIT(port), val);
  355. }
  356. if (flags.mask & BR_BCAST_FLOOD) {
  357. val = flags.val & BR_BCAST_FLOOD ? BIT(port) : 0;
  358. a5psw_reg_rmw(a5psw, A5PSW_BCAST_DEF_MASK, BIT(port), val);
  359. }
  360. return 0;
  361. }
  362. static void a5psw_port_stp_state_set(struct dsa_switch *ds, int port, u8 state)
  363. {
  364. bool learning_enabled, rx_enabled, tx_enabled;
  365. struct dsa_port *dp = dsa_to_port(ds, port);
  366. struct a5psw *a5psw = ds->priv;
  367. switch (state) {
  368. case BR_STATE_DISABLED:
  369. case BR_STATE_BLOCKING:
  370. case BR_STATE_LISTENING:
  371. rx_enabled = false;
  372. tx_enabled = false;
  373. learning_enabled = false;
  374. break;
  375. case BR_STATE_LEARNING:
  376. rx_enabled = false;
  377. tx_enabled = false;
  378. learning_enabled = dp->learning;
  379. break;
  380. case BR_STATE_FORWARDING:
  381. rx_enabled = true;
  382. tx_enabled = true;
  383. learning_enabled = dp->learning;
  384. break;
  385. default:
  386. dev_err(ds->dev, "invalid STP state: %d\n", state);
  387. return;
  388. }
  389. a5psw_port_learning_set(a5psw, port, learning_enabled);
  390. a5psw_port_rx_block_set(a5psw, port, !rx_enabled);
  391. a5psw_port_tx_enable(a5psw, port, tx_enabled);
  392. }
  393. static void a5psw_port_fast_age(struct dsa_switch *ds, int port)
  394. {
  395. struct a5psw *a5psw = ds->priv;
  396. a5psw_port_fdb_flush(a5psw, port);
  397. }
  398. static int a5psw_lk_execute_lookup(struct a5psw *a5psw, union lk_data *lk_data,
  399. u16 *entry)
  400. {
  401. u32 ctrl;
  402. int ret;
  403. a5psw_reg_writel(a5psw, A5PSW_LK_DATA_LO, lk_data->lo);
  404. a5psw_reg_writel(a5psw, A5PSW_LK_DATA_HI, lk_data->hi);
  405. ctrl = A5PSW_LK_ADDR_CTRL_LOOKUP;
  406. ret = a5psw_lk_execute_ctrl(a5psw, &ctrl);
  407. if (ret)
  408. return ret;
  409. *entry = ctrl & A5PSW_LK_ADDR_CTRL_ADDRESS;
  410. return 0;
  411. }
  412. static int a5psw_port_fdb_add(struct dsa_switch *ds, int port,
  413. const unsigned char *addr, u16 vid,
  414. struct dsa_db db)
  415. {
  416. struct a5psw *a5psw = ds->priv;
  417. union lk_data lk_data = {0};
  418. bool inc_learncount = false;
  419. int ret = 0;
  420. u16 entry;
  421. u32 reg;
  422. ether_addr_copy(lk_data.entry.mac, addr);
  423. lk_data.entry.port_mask = BIT(port);
  424. mutex_lock(&a5psw->lk_lock);
  425. /* Set the value to be written in the lookup table */
  426. ret = a5psw_lk_execute_lookup(a5psw, &lk_data, &entry);
  427. if (ret)
  428. goto lk_unlock;
  429. lk_data.hi = a5psw_reg_readl(a5psw, A5PSW_LK_DATA_HI);
  430. if (!lk_data.entry.valid) {
  431. inc_learncount = true;
  432. /* port_mask set to 0x1f when entry is not valid, clear it */
  433. lk_data.entry.port_mask = 0;
  434. lk_data.entry.prio = 0;
  435. }
  436. lk_data.entry.port_mask |= BIT(port);
  437. lk_data.entry.is_static = 1;
  438. lk_data.entry.valid = 1;
  439. a5psw_reg_writel(a5psw, A5PSW_LK_DATA_HI, lk_data.hi);
  440. reg = A5PSW_LK_ADDR_CTRL_WRITE | entry;
  441. ret = a5psw_lk_execute_ctrl(a5psw, &reg);
  442. if (ret)
  443. goto lk_unlock;
  444. if (inc_learncount) {
  445. reg = A5PSW_LK_LEARNCOUNT_MODE_INC;
  446. a5psw_reg_writel(a5psw, A5PSW_LK_LEARNCOUNT, reg);
  447. }
  448. lk_unlock:
  449. mutex_unlock(&a5psw->lk_lock);
  450. return ret;
  451. }
  452. static int a5psw_port_fdb_del(struct dsa_switch *ds, int port,
  453. const unsigned char *addr, u16 vid,
  454. struct dsa_db db)
  455. {
  456. struct a5psw *a5psw = ds->priv;
  457. union lk_data lk_data = {0};
  458. bool clear = false;
  459. u16 entry;
  460. u32 reg;
  461. int ret;
  462. ether_addr_copy(lk_data.entry.mac, addr);
  463. mutex_lock(&a5psw->lk_lock);
  464. ret = a5psw_lk_execute_lookup(a5psw, &lk_data, &entry);
  465. if (ret)
  466. goto lk_unlock;
  467. lk_data.hi = a5psw_reg_readl(a5psw, A5PSW_LK_DATA_HI);
  468. /* Our hardware does not associate any VID to the FDB entries so this
  469. * means that if two entries were added for the same mac but for
  470. * different VID, then, on the deletion of the first one, we would also
  471. * delete the second one. Since there is unfortunately nothing we can do
  472. * about that, do not return an error...
  473. */
  474. if (!lk_data.entry.valid)
  475. goto lk_unlock;
  476. lk_data.entry.port_mask &= ~BIT(port);
  477. /* If there is no more port in the mask, clear the entry */
  478. if (lk_data.entry.port_mask == 0)
  479. clear = true;
  480. a5psw_reg_writel(a5psw, A5PSW_LK_DATA_HI, lk_data.hi);
  481. reg = entry;
  482. if (clear)
  483. reg |= A5PSW_LK_ADDR_CTRL_CLEAR;
  484. else
  485. reg |= A5PSW_LK_ADDR_CTRL_WRITE;
  486. ret = a5psw_lk_execute_ctrl(a5psw, &reg);
  487. if (ret)
  488. goto lk_unlock;
  489. /* Decrement LEARNCOUNT */
  490. if (clear) {
  491. reg = A5PSW_LK_LEARNCOUNT_MODE_DEC;
  492. a5psw_reg_writel(a5psw, A5PSW_LK_LEARNCOUNT, reg);
  493. }
  494. lk_unlock:
  495. mutex_unlock(&a5psw->lk_lock);
  496. return ret;
  497. }
  498. static int a5psw_port_fdb_dump(struct dsa_switch *ds, int port,
  499. dsa_fdb_dump_cb_t *cb, void *data)
  500. {
  501. struct a5psw *a5psw = ds->priv;
  502. union lk_data lk_data;
  503. int i = 0, ret = 0;
  504. u32 reg;
  505. mutex_lock(&a5psw->lk_lock);
  506. for (i = 0; i < A5PSW_TABLE_ENTRIES; i++) {
  507. reg = A5PSW_LK_ADDR_CTRL_READ | A5PSW_LK_ADDR_CTRL_WAIT | i;
  508. ret = a5psw_lk_execute_ctrl(a5psw, &reg);
  509. if (ret)
  510. goto out_unlock;
  511. lk_data.hi = a5psw_reg_readl(a5psw, A5PSW_LK_DATA_HI);
  512. /* If entry is not valid or does not contain the port, skip */
  513. if (!lk_data.entry.valid ||
  514. !(lk_data.entry.port_mask & BIT(port)))
  515. continue;
  516. lk_data.lo = a5psw_reg_readl(a5psw, A5PSW_LK_DATA_LO);
  517. ret = cb(lk_data.entry.mac, 0, lk_data.entry.is_static, data);
  518. if (ret)
  519. goto out_unlock;
  520. }
  521. out_unlock:
  522. mutex_unlock(&a5psw->lk_lock);
  523. return ret;
  524. }
  525. static int a5psw_port_vlan_filtering(struct dsa_switch *ds, int port,
  526. bool vlan_filtering,
  527. struct netlink_ext_ack *extack)
  528. {
  529. u32 mask = BIT(port + A5PSW_VLAN_VERI_SHIFT) |
  530. BIT(port + A5PSW_VLAN_DISC_SHIFT);
  531. u32 val = vlan_filtering ? mask : 0;
  532. struct a5psw *a5psw = ds->priv;
  533. /* Disable/enable vlan tagging */
  534. a5psw_reg_rmw(a5psw, A5PSW_VLAN_IN_MODE_ENA, BIT(port),
  535. vlan_filtering ? BIT(port) : 0);
  536. /* Disable/enable vlan input filtering */
  537. a5psw_reg_rmw(a5psw, A5PSW_VLAN_VERIFY, mask, val);
  538. return 0;
  539. }
  540. static int a5psw_find_vlan_entry(struct a5psw *a5psw, u16 vid)
  541. {
  542. u32 vlan_res;
  543. int i;
  544. /* Find vlan for this port */
  545. for (i = 0; i < A5PSW_VLAN_COUNT; i++) {
  546. vlan_res = a5psw_reg_readl(a5psw, A5PSW_VLAN_RES(i));
  547. if (FIELD_GET(A5PSW_VLAN_RES_VLANID, vlan_res) == vid)
  548. return i;
  549. }
  550. return -1;
  551. }
  552. static int a5psw_new_vlan_res_entry(struct a5psw *a5psw, u16 newvid)
  553. {
  554. u32 vlan_res;
  555. int i;
  556. /* Find a free VLAN entry */
  557. for (i = 0; i < A5PSW_VLAN_COUNT; i++) {
  558. vlan_res = a5psw_reg_readl(a5psw, A5PSW_VLAN_RES(i));
  559. if (!(FIELD_GET(A5PSW_VLAN_RES_PORTMASK, vlan_res))) {
  560. vlan_res = FIELD_PREP(A5PSW_VLAN_RES_VLANID, newvid);
  561. a5psw_reg_writel(a5psw, A5PSW_VLAN_RES(i), vlan_res);
  562. return i;
  563. }
  564. }
  565. return -1;
  566. }
  567. static void a5psw_port_vlan_tagged_cfg(struct a5psw *a5psw,
  568. unsigned int vlan_res_id, int port,
  569. bool set)
  570. {
  571. u32 mask = A5PSW_VLAN_RES_WR_PORTMASK | A5PSW_VLAN_RES_RD_TAGMASK |
  572. BIT(port);
  573. u32 vlan_res_off = A5PSW_VLAN_RES(vlan_res_id);
  574. u32 val = A5PSW_VLAN_RES_WR_TAGMASK, reg;
  575. if (set)
  576. val |= BIT(port);
  577. /* Toggle tag mask read */
  578. a5psw_reg_writel(a5psw, vlan_res_off, A5PSW_VLAN_RES_RD_TAGMASK);
  579. reg = a5psw_reg_readl(a5psw, vlan_res_off);
  580. a5psw_reg_writel(a5psw, vlan_res_off, A5PSW_VLAN_RES_RD_TAGMASK);
  581. reg &= ~mask;
  582. reg |= val;
  583. a5psw_reg_writel(a5psw, vlan_res_off, reg);
  584. }
  585. static void a5psw_port_vlan_cfg(struct a5psw *a5psw, unsigned int vlan_res_id,
  586. int port, bool set)
  587. {
  588. u32 mask = A5PSW_VLAN_RES_WR_TAGMASK | BIT(port);
  589. u32 reg = A5PSW_VLAN_RES_WR_PORTMASK;
  590. if (set)
  591. reg |= BIT(port);
  592. a5psw_reg_rmw(a5psw, A5PSW_VLAN_RES(vlan_res_id), mask, reg);
  593. }
  594. static int a5psw_port_vlan_add(struct dsa_switch *ds, int port,
  595. const struct switchdev_obj_port_vlan *vlan,
  596. struct netlink_ext_ack *extack)
  597. {
  598. bool tagged = !(vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED);
  599. bool pvid = vlan->flags & BRIDGE_VLAN_INFO_PVID;
  600. struct a5psw *a5psw = ds->priv;
  601. u16 vid = vlan->vid;
  602. int vlan_res_id;
  603. vlan_res_id = a5psw_find_vlan_entry(a5psw, vid);
  604. if (vlan_res_id < 0) {
  605. vlan_res_id = a5psw_new_vlan_res_entry(a5psw, vid);
  606. if (vlan_res_id < 0)
  607. return -ENOSPC;
  608. }
  609. a5psw_port_vlan_cfg(a5psw, vlan_res_id, port, true);
  610. if (tagged)
  611. a5psw_port_vlan_tagged_cfg(a5psw, vlan_res_id, port, true);
  612. /* Configure port to tag with corresponding VID, but do not enable it
  613. * yet: wait for vlan filtering to be enabled to enable vlan port
  614. * tagging
  615. */
  616. if (pvid)
  617. a5psw_reg_writel(a5psw, A5PSW_SYSTEM_TAGINFO(port), vid);
  618. return 0;
  619. }
  620. static int a5psw_port_vlan_del(struct dsa_switch *ds, int port,
  621. const struct switchdev_obj_port_vlan *vlan)
  622. {
  623. struct a5psw *a5psw = ds->priv;
  624. u16 vid = vlan->vid;
  625. int vlan_res_id;
  626. vlan_res_id = a5psw_find_vlan_entry(a5psw, vid);
  627. if (vlan_res_id < 0)
  628. return -EINVAL;
  629. a5psw_port_vlan_cfg(a5psw, vlan_res_id, port, false);
  630. a5psw_port_vlan_tagged_cfg(a5psw, vlan_res_id, port, false);
  631. return 0;
  632. }
  633. static u64 a5psw_read_stat(struct a5psw *a5psw, u32 offset, int port)
  634. {
  635. u32 reg_lo, reg_hi;
  636. reg_lo = a5psw_reg_readl(a5psw, offset + A5PSW_PORT_OFFSET(port));
  637. /* A5PSW_STATS_HIWORD is latched on stat read */
  638. reg_hi = a5psw_reg_readl(a5psw, A5PSW_STATS_HIWORD);
  639. return ((u64)reg_hi << 32) | reg_lo;
  640. }
  641. static void a5psw_get_strings(struct dsa_switch *ds, int port, u32 stringset,
  642. uint8_t *data)
  643. {
  644. unsigned int u;
  645. if (stringset != ETH_SS_STATS)
  646. return;
  647. for (u = 0; u < ARRAY_SIZE(a5psw_stats); u++)
  648. ethtool_puts(&data, a5psw_stats[u].name);
  649. }
  650. static void a5psw_get_ethtool_stats(struct dsa_switch *ds, int port,
  651. uint64_t *data)
  652. {
  653. struct a5psw *a5psw = ds->priv;
  654. unsigned int u;
  655. for (u = 0; u < ARRAY_SIZE(a5psw_stats); u++)
  656. data[u] = a5psw_read_stat(a5psw, a5psw_stats[u].offset, port);
  657. }
  658. static int a5psw_get_sset_count(struct dsa_switch *ds, int port, int sset)
  659. {
  660. if (sset != ETH_SS_STATS)
  661. return 0;
  662. return ARRAY_SIZE(a5psw_stats);
  663. }
  664. static void a5psw_get_eth_mac_stats(struct dsa_switch *ds, int port,
  665. struct ethtool_eth_mac_stats *mac_stats)
  666. {
  667. struct a5psw *a5psw = ds->priv;
  668. #define RD(name) a5psw_read_stat(a5psw, A5PSW_##name, port)
  669. mac_stats->FramesTransmittedOK = RD(aFramesTransmittedOK);
  670. mac_stats->SingleCollisionFrames = RD(aSingleCollisions);
  671. mac_stats->MultipleCollisionFrames = RD(aMultipleCollisions);
  672. mac_stats->FramesReceivedOK = RD(aFramesReceivedOK);
  673. mac_stats->FrameCheckSequenceErrors = RD(aFrameCheckSequenceErrors);
  674. mac_stats->AlignmentErrors = RD(aAlignmentErrors);
  675. mac_stats->OctetsTransmittedOK = RD(aOctetsTransmittedOK);
  676. mac_stats->FramesWithDeferredXmissions = RD(aDeferred);
  677. mac_stats->LateCollisions = RD(aLateCollisions);
  678. mac_stats->FramesAbortedDueToXSColls = RD(aExcessiveCollisions);
  679. mac_stats->FramesLostDueToIntMACXmitError = RD(ifOutErrors);
  680. mac_stats->CarrierSenseErrors = RD(aCarrierSenseErrors);
  681. mac_stats->OctetsReceivedOK = RD(aOctetsReceivedOK);
  682. mac_stats->FramesLostDueToIntMACRcvError = RD(ifInErrors);
  683. mac_stats->MulticastFramesXmittedOK = RD(ifOutMulticastPkts);
  684. mac_stats->BroadcastFramesXmittedOK = RD(ifOutBroadcastPkts);
  685. mac_stats->FramesWithExcessiveDeferral = RD(aDeferred);
  686. mac_stats->MulticastFramesReceivedOK = RD(ifInMulticastPkts);
  687. mac_stats->BroadcastFramesReceivedOK = RD(ifInBroadcastPkts);
  688. #undef RD
  689. }
  690. static const struct ethtool_rmon_hist_range a5psw_rmon_ranges[] = {
  691. { 0, 64 },
  692. { 65, 127 },
  693. { 128, 255 },
  694. { 256, 511 },
  695. { 512, 1023 },
  696. { 1024, 1518 },
  697. { 1519, A5PSW_MAX_MTU },
  698. {}
  699. };
  700. static void a5psw_get_rmon_stats(struct dsa_switch *ds, int port,
  701. struct ethtool_rmon_stats *rmon_stats,
  702. const struct ethtool_rmon_hist_range **ranges)
  703. {
  704. struct a5psw *a5psw = ds->priv;
  705. #define RD(name) a5psw_read_stat(a5psw, A5PSW_##name, port)
  706. rmon_stats->undersize_pkts = RD(etherStatsUndersizePkts);
  707. rmon_stats->oversize_pkts = RD(etherStatsOversizePkts);
  708. rmon_stats->fragments = RD(etherStatsFragments);
  709. rmon_stats->jabbers = RD(etherStatsJabbers);
  710. rmon_stats->hist[0] = RD(etherStatsPkts64Octets);
  711. rmon_stats->hist[1] = RD(etherStatsPkts65to127Octets);
  712. rmon_stats->hist[2] = RD(etherStatsPkts128to255Octets);
  713. rmon_stats->hist[3] = RD(etherStatsPkts256to511Octets);
  714. rmon_stats->hist[4] = RD(etherStatsPkts512to1023Octets);
  715. rmon_stats->hist[5] = RD(etherStatsPkts1024to1518Octets);
  716. rmon_stats->hist[6] = RD(etherStatsPkts1519toXOctets);
  717. #undef RD
  718. *ranges = a5psw_rmon_ranges;
  719. }
  720. static void a5psw_get_eth_ctrl_stats(struct dsa_switch *ds, int port,
  721. struct ethtool_eth_ctrl_stats *ctrl_stats)
  722. {
  723. struct a5psw *a5psw = ds->priv;
  724. u64 stat;
  725. stat = a5psw_read_stat(a5psw, A5PSW_aTxPAUSEMACCtrlFrames, port);
  726. ctrl_stats->MACControlFramesTransmitted = stat;
  727. stat = a5psw_read_stat(a5psw, A5PSW_aRxPAUSEMACCtrlFrames, port);
  728. ctrl_stats->MACControlFramesReceived = stat;
  729. }
  730. static void a5psw_vlan_setup(struct a5psw *a5psw, int port)
  731. {
  732. u32 reg;
  733. /* Enable TAG always mode for the port, this is actually controlled
  734. * by VLAN_IN_MODE_ENA field which will be used for PVID insertion
  735. */
  736. reg = A5PSW_VLAN_IN_MODE_TAG_ALWAYS;
  737. reg <<= A5PSW_VLAN_IN_MODE_PORT_SHIFT(port);
  738. a5psw_reg_rmw(a5psw, A5PSW_VLAN_IN_MODE, A5PSW_VLAN_IN_MODE_PORT(port),
  739. reg);
  740. /* Set transparent mode for output frame manipulation, this will depend
  741. * on the VLAN_RES configuration mode
  742. */
  743. reg = A5PSW_VLAN_OUT_MODE_TRANSPARENT;
  744. reg <<= A5PSW_VLAN_OUT_MODE_PORT_SHIFT(port);
  745. a5psw_reg_rmw(a5psw, A5PSW_VLAN_OUT_MODE,
  746. A5PSW_VLAN_OUT_MODE_PORT(port), reg);
  747. }
  748. static int a5psw_setup(struct dsa_switch *ds)
  749. {
  750. struct a5psw *a5psw = ds->priv;
  751. int port, vlan, ret;
  752. struct dsa_port *dp;
  753. u32 reg;
  754. /* Validate that there is only 1 CPU port with index A5PSW_CPU_PORT */
  755. dsa_switch_for_each_cpu_port(dp, ds) {
  756. if (dp->index != A5PSW_CPU_PORT) {
  757. dev_err(a5psw->dev, "Invalid CPU port\n");
  758. return -EINVAL;
  759. }
  760. }
  761. /* Configure management port */
  762. reg = A5PSW_CPU_PORT | A5PSW_MGMT_CFG_ENABLE;
  763. a5psw_reg_writel(a5psw, A5PSW_MGMT_CFG, reg);
  764. /* Set pattern 0 to forward all frame to mgmt port */
  765. a5psw_reg_writel(a5psw, A5PSW_PATTERN_CTRL(A5PSW_PATTERN_MGMTFWD),
  766. A5PSW_PATTERN_CTRL_MGMTFWD);
  767. /* Enable port tagging */
  768. reg = FIELD_PREP(A5PSW_MGMT_TAG_CFG_TAGFIELD, ETH_P_DSA_A5PSW);
  769. reg |= A5PSW_MGMT_TAG_CFG_ENABLE | A5PSW_MGMT_TAG_CFG_ALL_FRAMES;
  770. a5psw_reg_writel(a5psw, A5PSW_MGMT_TAG_CFG, reg);
  771. /* Enable normal switch operation */
  772. reg = A5PSW_LK_ADDR_CTRL_BLOCKING | A5PSW_LK_ADDR_CTRL_LEARNING |
  773. A5PSW_LK_ADDR_CTRL_AGEING | A5PSW_LK_ADDR_CTRL_ALLOW_MIGR |
  774. A5PSW_LK_ADDR_CTRL_CLEAR_TABLE;
  775. a5psw_reg_writel(a5psw, A5PSW_LK_CTRL, reg);
  776. ret = readl_poll_timeout(a5psw->base + A5PSW_LK_CTRL, reg,
  777. !(reg & A5PSW_LK_ADDR_CTRL_CLEAR_TABLE),
  778. A5PSW_LK_BUSY_USEC_POLL, A5PSW_CTRL_TIMEOUT);
  779. if (ret) {
  780. dev_err(a5psw->dev, "Failed to clear lookup table\n");
  781. return ret;
  782. }
  783. /* Reset learn count to 0 */
  784. reg = A5PSW_LK_LEARNCOUNT_MODE_SET;
  785. a5psw_reg_writel(a5psw, A5PSW_LK_LEARNCOUNT, reg);
  786. /* Clear VLAN resource table */
  787. reg = A5PSW_VLAN_RES_WR_PORTMASK | A5PSW_VLAN_RES_WR_TAGMASK;
  788. for (vlan = 0; vlan < A5PSW_VLAN_COUNT; vlan++)
  789. a5psw_reg_writel(a5psw, A5PSW_VLAN_RES(vlan), reg);
  790. /* Reset all ports */
  791. dsa_switch_for_each_port(dp, ds) {
  792. port = dp->index;
  793. /* Reset the port */
  794. a5psw_reg_writel(a5psw, A5PSW_CMD_CFG(port),
  795. A5PSW_CMD_CFG_SW_RESET);
  796. /* Enable only CPU port */
  797. a5psw_port_enable_set(a5psw, port, dsa_port_is_cpu(dp));
  798. if (dsa_port_is_unused(dp))
  799. continue;
  800. /* Enable egress flooding and learning for CPU port */
  801. if (dsa_port_is_cpu(dp)) {
  802. a5psw_flooding_set_resolution(a5psw, port, true);
  803. a5psw_port_learning_set(a5psw, port, true);
  804. }
  805. /* Enable standalone mode for user ports */
  806. if (dsa_port_is_user(dp))
  807. a5psw_port_set_standalone(a5psw, port, true);
  808. a5psw_vlan_setup(a5psw, port);
  809. }
  810. return 0;
  811. }
  812. static const struct phylink_mac_ops a5psw_phylink_mac_ops = {
  813. .mac_select_pcs = a5psw_phylink_mac_select_pcs,
  814. .mac_config = a5psw_phylink_mac_config,
  815. .mac_link_down = a5psw_phylink_mac_link_down,
  816. .mac_link_up = a5psw_phylink_mac_link_up,
  817. };
  818. static const struct dsa_switch_ops a5psw_switch_ops = {
  819. .get_tag_protocol = a5psw_get_tag_protocol,
  820. .setup = a5psw_setup,
  821. .port_disable = a5psw_port_disable,
  822. .port_enable = a5psw_port_enable,
  823. .phylink_get_caps = a5psw_phylink_get_caps,
  824. .port_change_mtu = a5psw_port_change_mtu,
  825. .port_max_mtu = a5psw_port_max_mtu,
  826. .get_sset_count = a5psw_get_sset_count,
  827. .get_strings = a5psw_get_strings,
  828. .get_ethtool_stats = a5psw_get_ethtool_stats,
  829. .get_eth_mac_stats = a5psw_get_eth_mac_stats,
  830. .get_eth_ctrl_stats = a5psw_get_eth_ctrl_stats,
  831. .get_rmon_stats = a5psw_get_rmon_stats,
  832. .set_ageing_time = a5psw_set_ageing_time,
  833. .port_bridge_join = a5psw_port_bridge_join,
  834. .port_bridge_leave = a5psw_port_bridge_leave,
  835. .port_pre_bridge_flags = a5psw_port_pre_bridge_flags,
  836. .port_bridge_flags = a5psw_port_bridge_flags,
  837. .port_stp_state_set = a5psw_port_stp_state_set,
  838. .port_fast_age = a5psw_port_fast_age,
  839. .port_vlan_filtering = a5psw_port_vlan_filtering,
  840. .port_vlan_add = a5psw_port_vlan_add,
  841. .port_vlan_del = a5psw_port_vlan_del,
  842. .port_fdb_add = a5psw_port_fdb_add,
  843. .port_fdb_del = a5psw_port_fdb_del,
  844. .port_fdb_dump = a5psw_port_fdb_dump,
  845. .port_hsr_join = dsa_port_simple_hsr_join,
  846. .port_hsr_leave = dsa_port_simple_hsr_leave,
  847. };
  848. static int a5psw_mdio_wait_busy(struct a5psw *a5psw)
  849. {
  850. u32 status;
  851. int err;
  852. err = readl_poll_timeout(a5psw->base + A5PSW_MDIO_CFG_STATUS, status,
  853. !(status & A5PSW_MDIO_CFG_STATUS_BUSY), 10,
  854. 1000 * USEC_PER_MSEC);
  855. if (err)
  856. dev_err(a5psw->dev, "MDIO command timeout\n");
  857. return err;
  858. }
  859. static int a5psw_mdio_read(struct mii_bus *bus, int phy_id, int phy_reg)
  860. {
  861. struct a5psw *a5psw = bus->priv;
  862. u32 cmd, status;
  863. int ret;
  864. cmd = A5PSW_MDIO_COMMAND_READ;
  865. cmd |= FIELD_PREP(A5PSW_MDIO_COMMAND_REG_ADDR, phy_reg);
  866. cmd |= FIELD_PREP(A5PSW_MDIO_COMMAND_PHY_ADDR, phy_id);
  867. a5psw_reg_writel(a5psw, A5PSW_MDIO_COMMAND, cmd);
  868. ret = a5psw_mdio_wait_busy(a5psw);
  869. if (ret)
  870. return ret;
  871. ret = a5psw_reg_readl(a5psw, A5PSW_MDIO_DATA) & A5PSW_MDIO_DATA_MASK;
  872. status = a5psw_reg_readl(a5psw, A5PSW_MDIO_CFG_STATUS);
  873. if (status & A5PSW_MDIO_CFG_STATUS_READERR)
  874. return -EIO;
  875. return ret;
  876. }
  877. static int a5psw_mdio_write(struct mii_bus *bus, int phy_id, int phy_reg,
  878. u16 phy_data)
  879. {
  880. struct a5psw *a5psw = bus->priv;
  881. u32 cmd;
  882. cmd = FIELD_PREP(A5PSW_MDIO_COMMAND_REG_ADDR, phy_reg);
  883. cmd |= FIELD_PREP(A5PSW_MDIO_COMMAND_PHY_ADDR, phy_id);
  884. a5psw_reg_writel(a5psw, A5PSW_MDIO_COMMAND, cmd);
  885. a5psw_reg_writel(a5psw, A5PSW_MDIO_DATA, phy_data);
  886. return a5psw_mdio_wait_busy(a5psw);
  887. }
  888. static int a5psw_mdio_config(struct a5psw *a5psw, u32 mdio_freq)
  889. {
  890. unsigned long rate;
  891. unsigned long div;
  892. u32 cfgstatus;
  893. rate = clk_get_rate(a5psw->hclk);
  894. div = ((rate / mdio_freq) / 2);
  895. if (div > FIELD_MAX(A5PSW_MDIO_CFG_STATUS_CLKDIV) ||
  896. div < A5PSW_MDIO_CLK_DIV_MIN) {
  897. dev_err(a5psw->dev, "MDIO clock div %ld out of range\n", div);
  898. return -ERANGE;
  899. }
  900. cfgstatus = FIELD_PREP(A5PSW_MDIO_CFG_STATUS_CLKDIV, div);
  901. a5psw_reg_writel(a5psw, A5PSW_MDIO_CFG_STATUS, cfgstatus);
  902. return 0;
  903. }
  904. static int a5psw_probe_mdio(struct a5psw *a5psw, struct device_node *node)
  905. {
  906. struct device *dev = a5psw->dev;
  907. struct mii_bus *bus;
  908. u32 mdio_freq;
  909. int ret;
  910. if (of_property_read_u32(node, "clock-frequency", &mdio_freq))
  911. mdio_freq = A5PSW_MDIO_DEF_FREQ;
  912. ret = a5psw_mdio_config(a5psw, mdio_freq);
  913. if (ret)
  914. return ret;
  915. bus = devm_mdiobus_alloc(dev);
  916. if (!bus)
  917. return -ENOMEM;
  918. bus->name = "a5psw_mdio";
  919. bus->read = a5psw_mdio_read;
  920. bus->write = a5psw_mdio_write;
  921. bus->priv = a5psw;
  922. bus->parent = dev;
  923. snprintf(bus->id, MII_BUS_ID_SIZE, "%s", dev_name(dev));
  924. a5psw->mii_bus = bus;
  925. return devm_of_mdiobus_register(dev, bus, node);
  926. }
  927. static void a5psw_pcs_free(struct a5psw *a5psw)
  928. {
  929. int i;
  930. for (i = 0; i < ARRAY_SIZE(a5psw->pcs); i++) {
  931. if (a5psw->pcs[i])
  932. miic_destroy(a5psw->pcs[i]);
  933. }
  934. }
  935. static int a5psw_pcs_get(struct a5psw *a5psw)
  936. {
  937. struct device_node *ports, *port, *pcs_node;
  938. struct phylink_pcs *pcs;
  939. int ret;
  940. u32 reg;
  941. ports = of_get_child_by_name(a5psw->dev->of_node, "ethernet-ports");
  942. if (!ports)
  943. return -EINVAL;
  944. for_each_available_child_of_node(ports, port) {
  945. pcs_node = of_parse_phandle(port, "pcs-handle", 0);
  946. if (!pcs_node)
  947. continue;
  948. if (of_property_read_u32(port, "reg", &reg)) {
  949. ret = -EINVAL;
  950. goto free_pcs;
  951. }
  952. if (reg >= ARRAY_SIZE(a5psw->pcs)) {
  953. ret = -ENODEV;
  954. goto free_pcs;
  955. }
  956. pcs = miic_create(a5psw->dev, pcs_node);
  957. if (IS_ERR(pcs)) {
  958. dev_err(a5psw->dev, "Failed to create PCS for port %d\n",
  959. reg);
  960. ret = PTR_ERR(pcs);
  961. goto free_pcs;
  962. }
  963. a5psw->pcs[reg] = pcs;
  964. of_node_put(pcs_node);
  965. }
  966. of_node_put(ports);
  967. return 0;
  968. free_pcs:
  969. of_node_put(pcs_node);
  970. of_node_put(port);
  971. of_node_put(ports);
  972. a5psw_pcs_free(a5psw);
  973. return ret;
  974. }
  975. static int a5psw_probe(struct platform_device *pdev)
  976. {
  977. struct device *dev = &pdev->dev;
  978. struct device_node *mdio;
  979. struct dsa_switch *ds;
  980. struct a5psw *a5psw;
  981. int ret;
  982. a5psw = devm_kzalloc(dev, sizeof(*a5psw), GFP_KERNEL);
  983. if (!a5psw)
  984. return -ENOMEM;
  985. a5psw->dev = dev;
  986. mutex_init(&a5psw->lk_lock);
  987. spin_lock_init(&a5psw->reg_lock);
  988. a5psw->base = devm_platform_ioremap_resource(pdev, 0);
  989. if (IS_ERR(a5psw->base))
  990. return PTR_ERR(a5psw->base);
  991. a5psw->bridged_ports = BIT(A5PSW_CPU_PORT);
  992. ret = a5psw_pcs_get(a5psw);
  993. if (ret)
  994. return ret;
  995. a5psw->hclk = devm_clk_get_enabled(dev, "hclk");
  996. if (IS_ERR(a5psw->hclk)) {
  997. dev_err(dev, "failed get hclk clock\n");
  998. ret = PTR_ERR(a5psw->hclk);
  999. goto free_pcs;
  1000. }
  1001. a5psw->clk = devm_clk_get_enabled(dev, "clk");
  1002. if (IS_ERR(a5psw->clk)) {
  1003. dev_err(dev, "failed get clk_switch clock\n");
  1004. ret = PTR_ERR(a5psw->clk);
  1005. goto free_pcs;
  1006. }
  1007. mdio = of_get_available_child_by_name(dev->of_node, "mdio");
  1008. if (mdio) {
  1009. ret = a5psw_probe_mdio(a5psw, mdio);
  1010. of_node_put(mdio);
  1011. if (ret) {
  1012. dev_err(dev, "Failed to register MDIO: %d\n", ret);
  1013. goto free_pcs;
  1014. }
  1015. }
  1016. ds = &a5psw->ds;
  1017. ds->dev = dev;
  1018. ds->num_ports = A5PSW_PORTS_NUM;
  1019. ds->ops = &a5psw_switch_ops;
  1020. ds->phylink_mac_ops = &a5psw_phylink_mac_ops;
  1021. ds->priv = a5psw;
  1022. ret = dsa_register_switch(ds);
  1023. if (ret) {
  1024. dev_err(dev, "Failed to register DSA switch: %d\n", ret);
  1025. goto free_pcs;
  1026. }
  1027. return 0;
  1028. free_pcs:
  1029. a5psw_pcs_free(a5psw);
  1030. return ret;
  1031. }
  1032. static void a5psw_remove(struct platform_device *pdev)
  1033. {
  1034. struct a5psw *a5psw = platform_get_drvdata(pdev);
  1035. if (!a5psw)
  1036. return;
  1037. dsa_unregister_switch(&a5psw->ds);
  1038. a5psw_pcs_free(a5psw);
  1039. }
  1040. static void a5psw_shutdown(struct platform_device *pdev)
  1041. {
  1042. struct a5psw *a5psw = platform_get_drvdata(pdev);
  1043. if (!a5psw)
  1044. return;
  1045. dsa_switch_shutdown(&a5psw->ds);
  1046. platform_set_drvdata(pdev, NULL);
  1047. }
  1048. static const struct of_device_id a5psw_of_mtable[] = {
  1049. { .compatible = "renesas,rzn1-a5psw", },
  1050. { /* sentinel */ },
  1051. };
  1052. MODULE_DEVICE_TABLE(of, a5psw_of_mtable);
  1053. static struct platform_driver a5psw_driver = {
  1054. .driver = {
  1055. .name = "rzn1_a5psw",
  1056. .of_match_table = a5psw_of_mtable,
  1057. },
  1058. .probe = a5psw_probe,
  1059. .remove = a5psw_remove,
  1060. .shutdown = a5psw_shutdown,
  1061. };
  1062. module_platform_driver(a5psw_driver);
  1063. MODULE_LICENSE("GPL");
  1064. MODULE_DESCRIPTION("Renesas RZ/N1 Advanced 5-port Switch driver");
  1065. MODULE_AUTHOR("Clément Léger <clement.leger@bootlin.com>");