global2.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983
  1. /*
  2. * Marvell 88E6xxx Switch Global 2 Registers support (device address
  3. * 0x1C)
  4. *
  5. * Copyright (c) 2008 Marvell Semiconductor
  6. *
  7. * Copyright (c) 2016 Vivien Didelot <vivien.didelot@savoirfairelinux.com>
  8. *
  9. * This program is free software; you can redistribute it and/or modify
  10. * it under the terms of the GNU General Public License as published by
  11. * the Free Software Foundation; either version 2 of the License, or
  12. * (at your option) any later version.
  13. */
  14. #include <linux/irqdomain.h>
  15. #include "mv88e6xxx.h"
  16. #include "global2.h"
  17. #define ADDR_GLOBAL2 0x1c
  18. static int mv88e6xxx_g2_read(struct mv88e6xxx_chip *chip, int reg, u16 *val)
  19. {
  20. return mv88e6xxx_read(chip, ADDR_GLOBAL2, reg, val);
  21. }
  22. static int mv88e6xxx_g2_write(struct mv88e6xxx_chip *chip, int reg, u16 val)
  23. {
  24. return mv88e6xxx_write(chip, ADDR_GLOBAL2, reg, val);
  25. }
  26. static int mv88e6xxx_g2_update(struct mv88e6xxx_chip *chip, int reg, u16 update)
  27. {
  28. return mv88e6xxx_update(chip, ADDR_GLOBAL2, reg, update);
  29. }
  30. static int mv88e6xxx_g2_wait(struct mv88e6xxx_chip *chip, int reg, u16 mask)
  31. {
  32. return mv88e6xxx_wait(chip, ADDR_GLOBAL2, reg, mask);
  33. }
  34. /* Offset 0x02: Management Enable 2x */
  35. /* Offset 0x03: Management Enable 0x */
  36. int mv88e6095_g2_mgmt_rsvd2cpu(struct mv88e6xxx_chip *chip)
  37. {
  38. int err;
  39. /* Consider the frames with reserved multicast destination
  40. * addresses matching 01:80:c2:00:00:2x as MGMT.
  41. */
  42. if (mv88e6xxx_has(chip, MV88E6XXX_FLAG_G2_MGMT_EN_2X)) {
  43. err = mv88e6xxx_g2_write(chip, GLOBAL2_MGMT_EN_2X, 0xffff);
  44. if (err)
  45. return err;
  46. }
  47. /* Consider the frames with reserved multicast destination
  48. * addresses matching 01:80:c2:00:00:0x as MGMT.
  49. */
  50. if (mv88e6xxx_has(chip, MV88E6XXX_FLAG_G2_MGMT_EN_0X))
  51. return mv88e6xxx_g2_write(chip, GLOBAL2_MGMT_EN_0X, 0xffff);
  52. return 0;
  53. }
  54. /* Offset 0x06: Device Mapping Table register */
  55. static int mv88e6xxx_g2_device_mapping_write(struct mv88e6xxx_chip *chip,
  56. int target, int port)
  57. {
  58. u16 val = (target << 8) | (port & 0xf);
  59. return mv88e6xxx_g2_update(chip, GLOBAL2_DEVICE_MAPPING, val);
  60. }
  61. static int mv88e6xxx_g2_set_device_mapping(struct mv88e6xxx_chip *chip)
  62. {
  63. int target, port;
  64. int err;
  65. /* Initialize the routing port to the 32 possible target devices */
  66. for (target = 0; target < 32; ++target) {
  67. port = 0xf;
  68. if (target < DSA_MAX_SWITCHES) {
  69. port = chip->ds->rtable[target];
  70. if (port == DSA_RTABLE_NONE)
  71. port = 0xf;
  72. }
  73. err = mv88e6xxx_g2_device_mapping_write(chip, target, port);
  74. if (err)
  75. break;
  76. }
  77. return err;
  78. }
  79. /* Offset 0x07: Trunk Mask Table register */
  80. static int mv88e6xxx_g2_trunk_mask_write(struct mv88e6xxx_chip *chip, int num,
  81. bool hask, u16 mask)
  82. {
  83. const u16 port_mask = BIT(mv88e6xxx_num_ports(chip)) - 1;
  84. u16 val = (num << 12) | (mask & port_mask);
  85. if (hask)
  86. val |= GLOBAL2_TRUNK_MASK_HASK;
  87. return mv88e6xxx_g2_update(chip, GLOBAL2_TRUNK_MASK, val);
  88. }
  89. /* Offset 0x08: Trunk Mapping Table register */
  90. static int mv88e6xxx_g2_trunk_mapping_write(struct mv88e6xxx_chip *chip, int id,
  91. u16 map)
  92. {
  93. const u16 port_mask = BIT(mv88e6xxx_num_ports(chip)) - 1;
  94. u16 val = (id << 11) | (map & port_mask);
  95. return mv88e6xxx_g2_update(chip, GLOBAL2_TRUNK_MAPPING, val);
  96. }
  97. static int mv88e6xxx_g2_clear_trunk(struct mv88e6xxx_chip *chip)
  98. {
  99. const u16 port_mask = BIT(mv88e6xxx_num_ports(chip)) - 1;
  100. int i, err;
  101. /* Clear all eight possible Trunk Mask vectors */
  102. for (i = 0; i < 8; ++i) {
  103. err = mv88e6xxx_g2_trunk_mask_write(chip, i, false, port_mask);
  104. if (err)
  105. return err;
  106. }
  107. /* Clear all sixteen possible Trunk ID routing vectors */
  108. for (i = 0; i < 16; ++i) {
  109. err = mv88e6xxx_g2_trunk_mapping_write(chip, i, 0);
  110. if (err)
  111. return err;
  112. }
  113. return 0;
  114. }
  115. /* Offset 0x09: Ingress Rate Command register
  116. * Offset 0x0A: Ingress Rate Data register
  117. */
  118. static int mv88e6xxx_g2_clear_irl(struct mv88e6xxx_chip *chip)
  119. {
  120. int port, err;
  121. /* Init all Ingress Rate Limit resources of all ports */
  122. for (port = 0; port < mv88e6xxx_num_ports(chip); ++port) {
  123. /* XXX newer chips (like 88E6390) have different 2-bit ops */
  124. err = mv88e6xxx_g2_write(chip, GLOBAL2_IRL_CMD,
  125. GLOBAL2_IRL_CMD_OP_INIT_ALL |
  126. (port << 8));
  127. if (err)
  128. break;
  129. /* Wait for the operation to complete */
  130. err = mv88e6xxx_g2_wait(chip, GLOBAL2_IRL_CMD,
  131. GLOBAL2_IRL_CMD_BUSY);
  132. if (err)
  133. break;
  134. }
  135. return err;
  136. }
  137. /* Offset 0x0D: Switch MAC/WoL/WoF register */
  138. static int mv88e6xxx_g2_switch_mac_write(struct mv88e6xxx_chip *chip,
  139. unsigned int pointer, u8 data)
  140. {
  141. u16 val = (pointer << 8) | data;
  142. return mv88e6xxx_g2_update(chip, GLOBAL2_SWITCH_MAC, val);
  143. }
  144. int mv88e6xxx_g2_set_switch_mac(struct mv88e6xxx_chip *chip, u8 *addr)
  145. {
  146. int i, err;
  147. for (i = 0; i < 6; i++) {
  148. err = mv88e6xxx_g2_switch_mac_write(chip, i, addr[i]);
  149. if (err)
  150. break;
  151. }
  152. return err;
  153. }
  154. /* Offset 0x0F: Priority Override Table */
  155. static int mv88e6xxx_g2_pot_write(struct mv88e6xxx_chip *chip, int pointer,
  156. u8 data)
  157. {
  158. u16 val = (pointer << 8) | (data & 0x7);
  159. return mv88e6xxx_g2_update(chip, GLOBAL2_PRIO_OVERRIDE, val);
  160. }
  161. static int mv88e6xxx_g2_clear_pot(struct mv88e6xxx_chip *chip)
  162. {
  163. int i, err;
  164. /* Clear all sixteen possible Priority Override entries */
  165. for (i = 0; i < 16; i++) {
  166. err = mv88e6xxx_g2_pot_write(chip, i, 0);
  167. if (err)
  168. break;
  169. }
  170. return err;
  171. }
  172. /* Offset 0x14: EEPROM Command
  173. * Offset 0x15: EEPROM Data (for 16-bit data access)
  174. * Offset 0x15: EEPROM Addr (for 8-bit data access)
  175. */
  176. static int mv88e6xxx_g2_eeprom_wait(struct mv88e6xxx_chip *chip)
  177. {
  178. return mv88e6xxx_g2_wait(chip, GLOBAL2_EEPROM_CMD,
  179. GLOBAL2_EEPROM_CMD_BUSY |
  180. GLOBAL2_EEPROM_CMD_RUNNING);
  181. }
  182. static int mv88e6xxx_g2_eeprom_cmd(struct mv88e6xxx_chip *chip, u16 cmd)
  183. {
  184. int err;
  185. err = mv88e6xxx_g2_write(chip, GLOBAL2_EEPROM_CMD, cmd);
  186. if (err)
  187. return err;
  188. return mv88e6xxx_g2_eeprom_wait(chip);
  189. }
  190. static int mv88e6xxx_g2_eeprom_read8(struct mv88e6xxx_chip *chip,
  191. u16 addr, u8 *data)
  192. {
  193. u16 cmd = GLOBAL2_EEPROM_CMD_OP_READ;
  194. int err;
  195. err = mv88e6xxx_g2_eeprom_wait(chip);
  196. if (err)
  197. return err;
  198. err = mv88e6xxx_g2_write(chip, GLOBAL2_EEPROM_ADDR, addr);
  199. if (err)
  200. return err;
  201. err = mv88e6xxx_g2_eeprom_cmd(chip, cmd);
  202. if (err)
  203. return err;
  204. err = mv88e6xxx_g2_read(chip, GLOBAL2_EEPROM_CMD, &cmd);
  205. if (err)
  206. return err;
  207. *data = cmd & 0xff;
  208. return 0;
  209. }
  210. static int mv88e6xxx_g2_eeprom_write8(struct mv88e6xxx_chip *chip,
  211. u16 addr, u8 data)
  212. {
  213. u16 cmd = GLOBAL2_EEPROM_CMD_OP_WRITE | GLOBAL2_EEPROM_CMD_WRITE_EN;
  214. int err;
  215. err = mv88e6xxx_g2_eeprom_wait(chip);
  216. if (err)
  217. return err;
  218. err = mv88e6xxx_g2_write(chip, GLOBAL2_EEPROM_ADDR, addr);
  219. if (err)
  220. return err;
  221. return mv88e6xxx_g2_eeprom_cmd(chip, cmd | data);
  222. }
  223. static int mv88e6xxx_g2_eeprom_read16(struct mv88e6xxx_chip *chip,
  224. u8 addr, u16 *data)
  225. {
  226. u16 cmd = GLOBAL2_EEPROM_CMD_OP_READ | addr;
  227. int err;
  228. err = mv88e6xxx_g2_eeprom_wait(chip);
  229. if (err)
  230. return err;
  231. err = mv88e6xxx_g2_eeprom_cmd(chip, cmd);
  232. if (err)
  233. return err;
  234. return mv88e6xxx_g2_read(chip, GLOBAL2_EEPROM_DATA, data);
  235. }
  236. static int mv88e6xxx_g2_eeprom_write16(struct mv88e6xxx_chip *chip,
  237. u8 addr, u16 data)
  238. {
  239. u16 cmd = GLOBAL2_EEPROM_CMD_OP_WRITE | addr;
  240. int err;
  241. err = mv88e6xxx_g2_eeprom_wait(chip);
  242. if (err)
  243. return err;
  244. err = mv88e6xxx_g2_write(chip, GLOBAL2_EEPROM_DATA, data);
  245. if (err)
  246. return err;
  247. return mv88e6xxx_g2_eeprom_cmd(chip, cmd);
  248. }
  249. int mv88e6xxx_g2_get_eeprom8(struct mv88e6xxx_chip *chip,
  250. struct ethtool_eeprom *eeprom, u8 *data)
  251. {
  252. unsigned int offset = eeprom->offset;
  253. unsigned int len = eeprom->len;
  254. int err;
  255. eeprom->len = 0;
  256. while (len) {
  257. err = mv88e6xxx_g2_eeprom_read8(chip, offset, data);
  258. if (err)
  259. return err;
  260. eeprom->len++;
  261. offset++;
  262. data++;
  263. len--;
  264. }
  265. return 0;
  266. }
  267. int mv88e6xxx_g2_set_eeprom8(struct mv88e6xxx_chip *chip,
  268. struct ethtool_eeprom *eeprom, u8 *data)
  269. {
  270. unsigned int offset = eeprom->offset;
  271. unsigned int len = eeprom->len;
  272. int err;
  273. eeprom->len = 0;
  274. while (len) {
  275. err = mv88e6xxx_g2_eeprom_write8(chip, offset, *data);
  276. if (err)
  277. return err;
  278. eeprom->len++;
  279. offset++;
  280. data++;
  281. len--;
  282. }
  283. return 0;
  284. }
  285. int mv88e6xxx_g2_get_eeprom16(struct mv88e6xxx_chip *chip,
  286. struct ethtool_eeprom *eeprom, u8 *data)
  287. {
  288. unsigned int offset = eeprom->offset;
  289. unsigned int len = eeprom->len;
  290. u16 val;
  291. int err;
  292. eeprom->len = 0;
  293. if (offset & 1) {
  294. err = mv88e6xxx_g2_eeprom_read16(chip, offset >> 1, &val);
  295. if (err)
  296. return err;
  297. *data++ = (val >> 8) & 0xff;
  298. offset++;
  299. len--;
  300. eeprom->len++;
  301. }
  302. while (len >= 2) {
  303. err = mv88e6xxx_g2_eeprom_read16(chip, offset >> 1, &val);
  304. if (err)
  305. return err;
  306. *data++ = val & 0xff;
  307. *data++ = (val >> 8) & 0xff;
  308. offset += 2;
  309. len -= 2;
  310. eeprom->len += 2;
  311. }
  312. if (len) {
  313. err = mv88e6xxx_g2_eeprom_read16(chip, offset >> 1, &val);
  314. if (err)
  315. return err;
  316. *data++ = val & 0xff;
  317. offset++;
  318. len--;
  319. eeprom->len++;
  320. }
  321. return 0;
  322. }
  323. int mv88e6xxx_g2_set_eeprom16(struct mv88e6xxx_chip *chip,
  324. struct ethtool_eeprom *eeprom, u8 *data)
  325. {
  326. unsigned int offset = eeprom->offset;
  327. unsigned int len = eeprom->len;
  328. u16 val;
  329. int err;
  330. /* Ensure the RO WriteEn bit is set */
  331. err = mv88e6xxx_g2_read(chip, GLOBAL2_EEPROM_CMD, &val);
  332. if (err)
  333. return err;
  334. if (!(val & GLOBAL2_EEPROM_CMD_WRITE_EN))
  335. return -EROFS;
  336. eeprom->len = 0;
  337. if (offset & 1) {
  338. err = mv88e6xxx_g2_eeprom_read16(chip, offset >> 1, &val);
  339. if (err)
  340. return err;
  341. val = (*data++ << 8) | (val & 0xff);
  342. err = mv88e6xxx_g2_eeprom_write16(chip, offset >> 1, val);
  343. if (err)
  344. return err;
  345. offset++;
  346. len--;
  347. eeprom->len++;
  348. }
  349. while (len >= 2) {
  350. val = *data++;
  351. val |= *data++ << 8;
  352. err = mv88e6xxx_g2_eeprom_write16(chip, offset >> 1, val);
  353. if (err)
  354. return err;
  355. offset += 2;
  356. len -= 2;
  357. eeprom->len += 2;
  358. }
  359. if (len) {
  360. err = mv88e6xxx_g2_eeprom_read16(chip, offset >> 1, &val);
  361. if (err)
  362. return err;
  363. val = (val & 0xff00) | *data++;
  364. err = mv88e6xxx_g2_eeprom_write16(chip, offset >> 1, val);
  365. if (err)
  366. return err;
  367. offset++;
  368. len--;
  369. eeprom->len++;
  370. }
  371. return 0;
  372. }
  373. /* Offset 0x18: SMI PHY Command Register
  374. * Offset 0x19: SMI PHY Data Register
  375. */
  376. static int mv88e6xxx_g2_smi_phy_wait(struct mv88e6xxx_chip *chip)
  377. {
  378. return mv88e6xxx_g2_wait(chip, GLOBAL2_SMI_PHY_CMD,
  379. GLOBAL2_SMI_PHY_CMD_BUSY);
  380. }
  381. static int mv88e6xxx_g2_smi_phy_cmd(struct mv88e6xxx_chip *chip, u16 cmd)
  382. {
  383. int err;
  384. err = mv88e6xxx_g2_write(chip, GLOBAL2_SMI_PHY_CMD, cmd);
  385. if (err)
  386. return err;
  387. return mv88e6xxx_g2_smi_phy_wait(chip);
  388. }
  389. static int mv88e6xxx_g2_smi_phy_write_addr(struct mv88e6xxx_chip *chip,
  390. int addr, int device, int reg,
  391. bool external)
  392. {
  393. int cmd = SMI_CMD_OP_45_WRITE_ADDR | (addr << 5) | device;
  394. int err;
  395. if (external)
  396. cmd |= GLOBAL2_SMI_PHY_CMD_EXTERNAL;
  397. err = mv88e6xxx_g2_smi_phy_wait(chip);
  398. if (err)
  399. return err;
  400. err = mv88e6xxx_g2_write(chip, GLOBAL2_SMI_PHY_DATA, reg);
  401. if (err)
  402. return err;
  403. return mv88e6xxx_g2_smi_phy_cmd(chip, cmd);
  404. }
  405. int mv88e6xxx_g2_smi_phy_read_c45(struct mv88e6xxx_chip *chip, int addr,
  406. int reg_c45, u16 *val, bool external)
  407. {
  408. int device = (reg_c45 >> 16) & 0x1f;
  409. int reg = reg_c45 & 0xffff;
  410. int err;
  411. u16 cmd;
  412. err = mv88e6xxx_g2_smi_phy_write_addr(chip, addr, device, reg,
  413. external);
  414. if (err)
  415. return err;
  416. cmd = GLOBAL2_SMI_PHY_CMD_OP_45_READ_DATA | (addr << 5) | device;
  417. if (external)
  418. cmd |= GLOBAL2_SMI_PHY_CMD_EXTERNAL;
  419. err = mv88e6xxx_g2_smi_phy_cmd(chip, cmd);
  420. if (err)
  421. return err;
  422. err = mv88e6xxx_g2_read(chip, GLOBAL2_SMI_PHY_DATA, val);
  423. if (err)
  424. return err;
  425. err = *val;
  426. return 0;
  427. }
  428. int mv88e6xxx_g2_smi_phy_read_c22(struct mv88e6xxx_chip *chip, int addr,
  429. int reg, u16 *val, bool external)
  430. {
  431. u16 cmd = GLOBAL2_SMI_PHY_CMD_OP_22_READ_DATA | (addr << 5) | reg;
  432. int err;
  433. if (external)
  434. cmd |= GLOBAL2_SMI_PHY_CMD_EXTERNAL;
  435. err = mv88e6xxx_g2_smi_phy_wait(chip);
  436. if (err)
  437. return err;
  438. err = mv88e6xxx_g2_smi_phy_cmd(chip, cmd);
  439. if (err)
  440. return err;
  441. return mv88e6xxx_g2_read(chip, GLOBAL2_SMI_PHY_DATA, val);
  442. }
  443. int mv88e6xxx_g2_smi_phy_read(struct mv88e6xxx_chip *chip,
  444. struct mii_bus *bus,
  445. int addr, int reg, u16 *val)
  446. {
  447. struct mv88e6xxx_mdio_bus *mdio_bus = bus->priv;
  448. bool external = mdio_bus->external;
  449. if (reg & MII_ADDR_C45)
  450. return mv88e6xxx_g2_smi_phy_read_c45(chip, addr, reg, val,
  451. external);
  452. return mv88e6xxx_g2_smi_phy_read_c22(chip, addr, reg, val, external);
  453. }
  454. int mv88e6xxx_g2_smi_phy_write_c45(struct mv88e6xxx_chip *chip, int addr,
  455. int reg_c45, u16 val, bool external)
  456. {
  457. int device = (reg_c45 >> 16) & 0x1f;
  458. int reg = reg_c45 & 0xffff;
  459. int err;
  460. u16 cmd;
  461. err = mv88e6xxx_g2_smi_phy_write_addr(chip, addr, device, reg,
  462. external);
  463. if (err)
  464. return err;
  465. cmd = GLOBAL2_SMI_PHY_CMD_OP_45_WRITE_DATA | (addr << 5) | device;
  466. if (external)
  467. cmd |= GLOBAL2_SMI_PHY_CMD_EXTERNAL;
  468. err = mv88e6xxx_g2_write(chip, GLOBAL2_SMI_PHY_DATA, val);
  469. if (err)
  470. return err;
  471. err = mv88e6xxx_g2_smi_phy_cmd(chip, cmd);
  472. if (err)
  473. return err;
  474. return 0;
  475. }
  476. int mv88e6xxx_g2_smi_phy_write_c22(struct mv88e6xxx_chip *chip, int addr,
  477. int reg, u16 val, bool external)
  478. {
  479. u16 cmd = GLOBAL2_SMI_PHY_CMD_OP_22_WRITE_DATA | (addr << 5) | reg;
  480. int err;
  481. if (external)
  482. cmd |= GLOBAL2_SMI_PHY_CMD_EXTERNAL;
  483. err = mv88e6xxx_g2_smi_phy_wait(chip);
  484. if (err)
  485. return err;
  486. err = mv88e6xxx_g2_write(chip, GLOBAL2_SMI_PHY_DATA, val);
  487. if (err)
  488. return err;
  489. return mv88e6xxx_g2_smi_phy_cmd(chip, cmd);
  490. }
  491. int mv88e6xxx_g2_smi_phy_write(struct mv88e6xxx_chip *chip,
  492. struct mii_bus *bus,
  493. int addr, int reg, u16 val)
  494. {
  495. struct mv88e6xxx_mdio_bus *mdio_bus = bus->priv;
  496. bool external = mdio_bus->external;
  497. if (reg & MII_ADDR_C45)
  498. return mv88e6xxx_g2_smi_phy_write_c45(chip, addr, reg, val,
  499. external);
  500. return mv88e6xxx_g2_smi_phy_write_c22(chip, addr, reg, val, external);
  501. }
  502. static int mv88e6097_watchdog_action(struct mv88e6xxx_chip *chip, int irq)
  503. {
  504. u16 reg;
  505. mv88e6xxx_g2_read(chip, GLOBAL2_WDOG_CONTROL, &reg);
  506. dev_info(chip->dev, "Watchdog event: 0x%04x", reg);
  507. return IRQ_HANDLED;
  508. }
  509. static void mv88e6097_watchdog_free(struct mv88e6xxx_chip *chip)
  510. {
  511. u16 reg;
  512. mv88e6xxx_g2_read(chip, GLOBAL2_WDOG_CONTROL, &reg);
  513. reg &= ~(GLOBAL2_WDOG_CONTROL_EGRESS_ENABLE |
  514. GLOBAL2_WDOG_CONTROL_QC_ENABLE);
  515. mv88e6xxx_g2_write(chip, GLOBAL2_WDOG_CONTROL, reg);
  516. }
  517. static int mv88e6097_watchdog_setup(struct mv88e6xxx_chip *chip)
  518. {
  519. return mv88e6xxx_g2_write(chip, GLOBAL2_WDOG_CONTROL,
  520. GLOBAL2_WDOG_CONTROL_EGRESS_ENABLE |
  521. GLOBAL2_WDOG_CONTROL_QC_ENABLE |
  522. GLOBAL2_WDOG_CONTROL_SWRESET);
  523. }
  524. const struct mv88e6xxx_irq_ops mv88e6097_watchdog_ops = {
  525. .irq_action = mv88e6097_watchdog_action,
  526. .irq_setup = mv88e6097_watchdog_setup,
  527. .irq_free = mv88e6097_watchdog_free,
  528. };
  529. static int mv88e6390_watchdog_setup(struct mv88e6xxx_chip *chip)
  530. {
  531. return mv88e6xxx_g2_update(chip, GLOBAL2_WDOG_CONTROL,
  532. GLOBAL2_WDOG_INT_ENABLE |
  533. GLOBAL2_WDOG_CUT_THROUGH |
  534. GLOBAL2_WDOG_QUEUE_CONTROLLER |
  535. GLOBAL2_WDOG_EGRESS |
  536. GLOBAL2_WDOG_FORCE_IRQ);
  537. }
  538. static int mv88e6390_watchdog_action(struct mv88e6xxx_chip *chip, int irq)
  539. {
  540. int err;
  541. u16 reg;
  542. mv88e6xxx_g2_write(chip, GLOBAL2_WDOG_CONTROL, GLOBAL2_WDOG_EVENT);
  543. err = mv88e6xxx_g2_read(chip, GLOBAL2_WDOG_CONTROL, &reg);
  544. dev_info(chip->dev, "Watchdog event: 0x%04x",
  545. reg & GLOBAL2_WDOG_DATA_MASK);
  546. mv88e6xxx_g2_write(chip, GLOBAL2_WDOG_CONTROL, GLOBAL2_WDOG_HISTORY);
  547. err = mv88e6xxx_g2_read(chip, GLOBAL2_WDOG_CONTROL, &reg);
  548. dev_info(chip->dev, "Watchdog history: 0x%04x",
  549. reg & GLOBAL2_WDOG_DATA_MASK);
  550. /* Trigger a software reset to try to recover the switch */
  551. if (chip->info->ops->reset)
  552. chip->info->ops->reset(chip);
  553. mv88e6390_watchdog_setup(chip);
  554. return IRQ_HANDLED;
  555. }
  556. static void mv88e6390_watchdog_free(struct mv88e6xxx_chip *chip)
  557. {
  558. mv88e6xxx_g2_update(chip, GLOBAL2_WDOG_CONTROL,
  559. GLOBAL2_WDOG_INT_ENABLE);
  560. }
  561. const struct mv88e6xxx_irq_ops mv88e6390_watchdog_ops = {
  562. .irq_action = mv88e6390_watchdog_action,
  563. .irq_setup = mv88e6390_watchdog_setup,
  564. .irq_free = mv88e6390_watchdog_free,
  565. };
  566. static irqreturn_t mv88e6xxx_g2_watchdog_thread_fn(int irq, void *dev_id)
  567. {
  568. struct mv88e6xxx_chip *chip = dev_id;
  569. irqreturn_t ret = IRQ_NONE;
  570. mutex_lock(&chip->reg_lock);
  571. if (chip->info->ops->watchdog_ops->irq_action)
  572. ret = chip->info->ops->watchdog_ops->irq_action(chip, irq);
  573. mutex_unlock(&chip->reg_lock);
  574. return ret;
  575. }
  576. static void mv88e6xxx_g2_watchdog_free(struct mv88e6xxx_chip *chip)
  577. {
  578. mutex_lock(&chip->reg_lock);
  579. if (chip->info->ops->watchdog_ops->irq_free)
  580. chip->info->ops->watchdog_ops->irq_free(chip);
  581. mutex_unlock(&chip->reg_lock);
  582. free_irq(chip->watchdog_irq, chip);
  583. irq_dispose_mapping(chip->watchdog_irq);
  584. }
  585. static int mv88e6xxx_g2_watchdog_setup(struct mv88e6xxx_chip *chip)
  586. {
  587. int err;
  588. chip->watchdog_irq = irq_find_mapping(chip->g2_irq.domain,
  589. GLOBAL2_INT_SOURCE_WATCHDOG);
  590. if (chip->watchdog_irq < 0)
  591. return chip->watchdog_irq;
  592. err = request_threaded_irq(chip->watchdog_irq, NULL,
  593. mv88e6xxx_g2_watchdog_thread_fn,
  594. IRQF_ONESHOT | IRQF_TRIGGER_FALLING,
  595. "mv88e6xxx-watchdog", chip);
  596. if (err)
  597. return err;
  598. mutex_lock(&chip->reg_lock);
  599. if (chip->info->ops->watchdog_ops->irq_setup)
  600. err = chip->info->ops->watchdog_ops->irq_setup(chip);
  601. mutex_unlock(&chip->reg_lock);
  602. return err;
  603. }
  604. static void mv88e6xxx_g2_irq_mask(struct irq_data *d)
  605. {
  606. struct mv88e6xxx_chip *chip = irq_data_get_irq_chip_data(d);
  607. unsigned int n = d->hwirq;
  608. chip->g2_irq.masked |= (1 << n);
  609. }
  610. static void mv88e6xxx_g2_irq_unmask(struct irq_data *d)
  611. {
  612. struct mv88e6xxx_chip *chip = irq_data_get_irq_chip_data(d);
  613. unsigned int n = d->hwirq;
  614. chip->g2_irq.masked &= ~(1 << n);
  615. }
  616. static irqreturn_t mv88e6xxx_g2_irq_thread_fn(int irq, void *dev_id)
  617. {
  618. struct mv88e6xxx_chip *chip = dev_id;
  619. unsigned int nhandled = 0;
  620. unsigned int sub_irq;
  621. unsigned int n;
  622. int err;
  623. u16 reg;
  624. mutex_lock(&chip->reg_lock);
  625. err = mv88e6xxx_g2_read(chip, GLOBAL2_INT_SOURCE, &reg);
  626. mutex_unlock(&chip->reg_lock);
  627. if (err)
  628. goto out;
  629. for (n = 0; n < 16; ++n) {
  630. if (reg & (1 << n)) {
  631. sub_irq = irq_find_mapping(chip->g2_irq.domain, n);
  632. handle_nested_irq(sub_irq);
  633. ++nhandled;
  634. }
  635. }
  636. out:
  637. return (nhandled > 0 ? IRQ_HANDLED : IRQ_NONE);
  638. }
  639. static void mv88e6xxx_g2_irq_bus_lock(struct irq_data *d)
  640. {
  641. struct mv88e6xxx_chip *chip = irq_data_get_irq_chip_data(d);
  642. mutex_lock(&chip->reg_lock);
  643. }
  644. static void mv88e6xxx_g2_irq_bus_sync_unlock(struct irq_data *d)
  645. {
  646. struct mv88e6xxx_chip *chip = irq_data_get_irq_chip_data(d);
  647. mv88e6xxx_g2_write(chip, GLOBAL2_INT_MASK, ~chip->g2_irq.masked);
  648. mutex_unlock(&chip->reg_lock);
  649. }
  650. static struct irq_chip mv88e6xxx_g2_irq_chip = {
  651. .name = "mv88e6xxx-g2",
  652. .irq_mask = mv88e6xxx_g2_irq_mask,
  653. .irq_unmask = mv88e6xxx_g2_irq_unmask,
  654. .irq_bus_lock = mv88e6xxx_g2_irq_bus_lock,
  655. .irq_bus_sync_unlock = mv88e6xxx_g2_irq_bus_sync_unlock,
  656. };
  657. static int mv88e6xxx_g2_irq_domain_map(struct irq_domain *d,
  658. unsigned int irq,
  659. irq_hw_number_t hwirq)
  660. {
  661. struct mv88e6xxx_chip *chip = d->host_data;
  662. irq_set_chip_data(irq, d->host_data);
  663. irq_set_chip_and_handler(irq, &chip->g2_irq.chip, handle_level_irq);
  664. irq_set_noprobe(irq);
  665. return 0;
  666. }
  667. static const struct irq_domain_ops mv88e6xxx_g2_irq_domain_ops = {
  668. .map = mv88e6xxx_g2_irq_domain_map,
  669. .xlate = irq_domain_xlate_twocell,
  670. };
  671. void mv88e6xxx_g2_irq_free(struct mv88e6xxx_chip *chip)
  672. {
  673. int irq, virq;
  674. mv88e6xxx_g2_watchdog_free(chip);
  675. free_irq(chip->device_irq, chip);
  676. irq_dispose_mapping(chip->device_irq);
  677. for (irq = 0; irq < 16; irq++) {
  678. virq = irq_find_mapping(chip->g2_irq.domain, irq);
  679. irq_dispose_mapping(virq);
  680. }
  681. irq_domain_remove(chip->g2_irq.domain);
  682. }
  683. int mv88e6xxx_g2_irq_setup(struct mv88e6xxx_chip *chip)
  684. {
  685. int err, irq, virq;
  686. if (!chip->dev->of_node)
  687. return -EINVAL;
  688. chip->g2_irq.domain = irq_domain_add_simple(
  689. chip->dev->of_node, 16, 0, &mv88e6xxx_g2_irq_domain_ops, chip);
  690. if (!chip->g2_irq.domain)
  691. return -ENOMEM;
  692. for (irq = 0; irq < 16; irq++)
  693. irq_create_mapping(chip->g2_irq.domain, irq);
  694. chip->g2_irq.chip = mv88e6xxx_g2_irq_chip;
  695. chip->g2_irq.masked = ~0;
  696. chip->device_irq = irq_find_mapping(chip->g1_irq.domain,
  697. GLOBAL_STATUS_IRQ_DEVICE);
  698. if (chip->device_irq < 0) {
  699. err = chip->device_irq;
  700. goto out;
  701. }
  702. err = request_threaded_irq(chip->device_irq, NULL,
  703. mv88e6xxx_g2_irq_thread_fn,
  704. IRQF_ONESHOT, "mv88e6xxx-g1", chip);
  705. if (err)
  706. goto out;
  707. return mv88e6xxx_g2_watchdog_setup(chip);
  708. out:
  709. for (irq = 0; irq < 16; irq++) {
  710. virq = irq_find_mapping(chip->g2_irq.domain, irq);
  711. irq_dispose_mapping(virq);
  712. }
  713. irq_domain_remove(chip->g2_irq.domain);
  714. return err;
  715. }
  716. int mv88e6xxx_g2_setup(struct mv88e6xxx_chip *chip)
  717. {
  718. u16 reg;
  719. int err;
  720. /* Ignore removed tag data on doubly tagged packets, disable
  721. * flow control messages, force flow control priority to the
  722. * highest, and send all special multicast frames to the CPU
  723. * port at the highest priority.
  724. */
  725. reg = GLOBAL2_SWITCH_MGMT_FORCE_FLOW_CTRL_PRI | (0x7 << 4);
  726. if (mv88e6xxx_has(chip, MV88E6XXX_FLAG_G2_MGMT_EN_0X) ||
  727. mv88e6xxx_has(chip, MV88E6XXX_FLAG_G2_MGMT_EN_2X))
  728. reg |= GLOBAL2_SWITCH_MGMT_RSVD2CPU | 0x7;
  729. err = mv88e6xxx_g2_write(chip, GLOBAL2_SWITCH_MGMT, reg);
  730. if (err)
  731. return err;
  732. /* Program the DSA routing table. */
  733. err = mv88e6xxx_g2_set_device_mapping(chip);
  734. if (err)
  735. return err;
  736. /* Clear all trunk masks and mapping. */
  737. err = mv88e6xxx_g2_clear_trunk(chip);
  738. if (err)
  739. return err;
  740. if (mv88e6xxx_has(chip, MV88E6XXX_FLAGS_IRL)) {
  741. /* Disable ingress rate limiting by resetting all per port
  742. * ingress rate limit resources to their initial state.
  743. */
  744. err = mv88e6xxx_g2_clear_irl(chip);
  745. if (err)
  746. return err;
  747. }
  748. if (mv88e6xxx_has(chip, MV88E6XXX_FLAGS_PVT)) {
  749. /* Initialize Cross-chip Port VLAN Table to reset defaults */
  750. err = mv88e6xxx_g2_write(chip, GLOBAL2_PVT_ADDR,
  751. GLOBAL2_PVT_ADDR_OP_INIT_ONES);
  752. if (err)
  753. return err;
  754. }
  755. if (mv88e6xxx_has(chip, MV88E6XXX_FLAG_G2_POT)) {
  756. /* Clear the priority override table. */
  757. err = mv88e6xxx_g2_clear_pot(chip);
  758. if (err)
  759. return err;
  760. }
  761. return 0;
  762. }