rtl8366s.c 29 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168
  1. /*
  2. * Platform driver for the Realtek RTL8366S ethernet switch
  3. *
  4. * Copyright (C) 2009-2010 Gabor Juhos <[email protected]>
  5. * Copyright (C) 2010 Antti Seppälä <[email protected]>
  6. *
  7. * This program is free software; you can redistribute it and/or modify it
  8. * under the terms of the GNU General Public License version 2 as published
  9. * by the Free Software Foundation.
  10. */
  11. #include <linux/kernel.h>
  12. #include <linux/module.h>
  13. #include <linux/init.h>
  14. #include <linux/platform_device.h>
  15. #include <linux/delay.h>
  16. #include <linux/skbuff.h>
  17. #include <linux/rtl8366s.h>
  18. #include "rtl8366_smi.h"
  19. #define RTL8366S_DRIVER_DESC "Realtek RTL8366S ethernet switch driver"
  20. #define RTL8366S_DRIVER_VER "0.2.2"
  21. #define RTL8366S_PHY_NO_MAX 4
  22. #define RTL8366S_PHY_PAGE_MAX 7
  23. #define RTL8366S_PHY_ADDR_MAX 31
  24. #define RTL8366S_PHY_WAN 4
  25. /* Switch Global Configuration register */
  26. #define RTL8366S_SGCR 0x0000
  27. #define RTL8366S_SGCR_EN_BC_STORM_CTRL BIT(0)
  28. #define RTL8366S_SGCR_MAX_LENGTH(_x) (_x << 4)
  29. #define RTL8366S_SGCR_MAX_LENGTH_MASK RTL8366S_SGCR_MAX_LENGTH(0x3)
  30. #define RTL8366S_SGCR_MAX_LENGTH_1522 RTL8366S_SGCR_MAX_LENGTH(0x0)
  31. #define RTL8366S_SGCR_MAX_LENGTH_1536 RTL8366S_SGCR_MAX_LENGTH(0x1)
  32. #define RTL8366S_SGCR_MAX_LENGTH_1552 RTL8366S_SGCR_MAX_LENGTH(0x2)
  33. #define RTL8366S_SGCR_MAX_LENGTH_16000 RTL8366S_SGCR_MAX_LENGTH(0x3)
  34. #define RTL8366S_SGCR_EN_VLAN BIT(13)
  35. /* Port Enable Control register */
  36. #define RTL8366S_PECR 0x0001
  37. /* Switch Security Control registers */
  38. #define RTL8366S_SSCR0 0x0002
  39. #define RTL8366S_SSCR1 0x0003
  40. #define RTL8366S_SSCR2 0x0004
  41. #define RTL8366S_SSCR2_DROP_UNKNOWN_DA BIT(0)
  42. #define RTL8366S_RESET_CTRL_REG 0x0100
  43. #define RTL8366S_CHIP_CTRL_RESET_HW 1
  44. #define RTL8366S_CHIP_CTRL_RESET_SW (1 << 1)
  45. #define RTL8366S_CHIP_VERSION_CTRL_REG 0x0104
  46. #define RTL8366S_CHIP_VERSION_MASK 0xf
  47. #define RTL8366S_CHIP_ID_REG 0x0105
  48. #define RTL8366S_CHIP_ID_8366 0x8366
  49. /* PHY registers control */
  50. #define RTL8366S_PHY_ACCESS_CTRL_REG 0x8028
  51. #define RTL8366S_PHY_ACCESS_DATA_REG 0x8029
  52. #define RTL8366S_PHY_CTRL_READ 1
  53. #define RTL8366S_PHY_CTRL_WRITE 0
  54. #define RTL8366S_PHY_REG_MASK 0x1f
  55. #define RTL8366S_PHY_PAGE_OFFSET 5
  56. #define RTL8366S_PHY_PAGE_MASK (0x7 << 5)
  57. #define RTL8366S_PHY_NO_OFFSET 9
  58. #define RTL8366S_PHY_NO_MASK (0x1f << 9)
  59. /* LED control registers */
  60. #define RTL8366S_LED_BLINKRATE_REG 0x0420
  61. #define RTL8366S_LED_BLINKRATE_BIT 0
  62. #define RTL8366S_LED_BLINKRATE_MASK 0x0007
  63. #define RTL8366S_LED_CTRL_REG 0x0421
  64. #define RTL8366S_LED_0_1_CTRL_REG 0x0422
  65. #define RTL8366S_LED_2_3_CTRL_REG 0x0423
  66. #define RTL8366S_MIB_COUNT 33
  67. #define RTL8366S_GLOBAL_MIB_COUNT 1
  68. #define RTL8366S_MIB_COUNTER_PORT_OFFSET 0x0040
  69. #define RTL8366S_MIB_COUNTER_BASE 0x1000
  70. #define RTL8366S_MIB_COUNTER_PORT_OFFSET2 0x0008
  71. #define RTL8366S_MIB_COUNTER_BASE2 0x1180
  72. #define RTL8366S_MIB_CTRL_REG 0x11F0
  73. #define RTL8366S_MIB_CTRL_USER_MASK 0x01FF
  74. #define RTL8366S_MIB_CTRL_BUSY_MASK 0x0001
  75. #define RTL8366S_MIB_CTRL_RESET_MASK 0x0002
  76. #define RTL8366S_MIB_CTRL_GLOBAL_RESET_MASK 0x0004
  77. #define RTL8366S_MIB_CTRL_PORT_RESET_BIT 0x0003
  78. #define RTL8366S_MIB_CTRL_PORT_RESET_MASK 0x01FC
  79. #define RTL8366S_PORT_VLAN_CTRL_BASE 0x0058
  80. #define RTL8366S_PORT_VLAN_CTRL_REG(_p) \
  81. (RTL8366S_PORT_VLAN_CTRL_BASE + (_p) / 4)
  82. #define RTL8366S_PORT_VLAN_CTRL_MASK 0xf
  83. #define RTL8366S_PORT_VLAN_CTRL_SHIFT(_p) (4 * ((_p) % 4))
  84. #define RTL8366S_VLAN_TABLE_READ_BASE 0x018B
  85. #define RTL8366S_VLAN_TABLE_WRITE_BASE 0x0185
  86. #define RTL8366S_VLAN_TB_CTRL_REG 0x010F
  87. #define RTL8366S_TABLE_ACCESS_CTRL_REG 0x0180
  88. #define RTL8366S_TABLE_VLAN_READ_CTRL 0x0E01
  89. #define RTL8366S_TABLE_VLAN_WRITE_CTRL 0x0F01
  90. #define RTL8366S_VLAN_MC_BASE(_x) (0x0016 + (_x) * 2)
  91. #define RTL8366S_VLAN_MEMBERINGRESS_REG 0x0379
  92. #define RTL8366S_PORT_LINK_STATUS_BASE 0x0060
  93. #define RTL8366S_PORT_STATUS_SPEED_MASK 0x0003
  94. #define RTL8366S_PORT_STATUS_DUPLEX_MASK 0x0004
  95. #define RTL8366S_PORT_STATUS_LINK_MASK 0x0010
  96. #define RTL8366S_PORT_STATUS_TXPAUSE_MASK 0x0020
  97. #define RTL8366S_PORT_STATUS_RXPAUSE_MASK 0x0040
  98. #define RTL8366S_PORT_STATUS_AN_MASK 0x0080
  99. #define RTL8366S_PORT_NUM_CPU 5
  100. #define RTL8366S_NUM_PORTS 6
  101. #define RTL8366S_NUM_VLANS 16
  102. #define RTL8366S_NUM_LEDGROUPS 4
  103. #define RTL8366S_NUM_VIDS 4096
  104. #define RTL8366S_PRIORITYMAX 7
  105. #define RTL8366S_FIDMAX 7
  106. #define RTL8366S_PORT_1 (1 << 0) /* In userspace port 0 */
  107. #define RTL8366S_PORT_2 (1 << 1) /* In userspace port 1 */
  108. #define RTL8366S_PORT_3 (1 << 2) /* In userspace port 2 */
  109. #define RTL8366S_PORT_4 (1 << 3) /* In userspace port 3 */
  110. #define RTL8366S_PORT_UNKNOWN (1 << 4) /* No known connection */
  111. #define RTL8366S_PORT_CPU (1 << 5) /* CPU port */
  112. #define RTL8366S_PORT_ALL (RTL8366S_PORT_1 | \
  113. RTL8366S_PORT_2 | \
  114. RTL8366S_PORT_3 | \
  115. RTL8366S_PORT_4 | \
  116. RTL8366S_PORT_UNKNOWN | \
  117. RTL8366S_PORT_CPU)
  118. #define RTL8366S_PORT_ALL_BUT_CPU (RTL8366S_PORT_1 | \
  119. RTL8366S_PORT_2 | \
  120. RTL8366S_PORT_3 | \
  121. RTL8366S_PORT_4 | \
  122. RTL8366S_PORT_UNKNOWN)
  123. #define RTL8366S_PORT_ALL_EXTERNAL (RTL8366S_PORT_1 | \
  124. RTL8366S_PORT_2 | \
  125. RTL8366S_PORT_3 | \
  126. RTL8366S_PORT_4)
  127. #define RTL8366S_PORT_ALL_INTERNAL (RTL8366S_PORT_UNKNOWN | \
  128. RTL8366S_PORT_CPU)
  129. #define RTL8366S_VLAN_VID_MASK 0xfff
  130. #define RTL8366S_VLAN_PRIORITY_SHIFT 12
  131. #define RTL8366S_VLAN_PRIORITY_MASK 0x7
  132. #define RTL8366S_VLAN_MEMBER_MASK 0x3f
  133. #define RTL8366S_VLAN_UNTAG_SHIFT 6
  134. #define RTL8366S_VLAN_UNTAG_MASK 0x3f
  135. #define RTL8366S_VLAN_FID_SHIFT 12
  136. #define RTL8366S_VLAN_FID_MASK 0x7
  137. static struct rtl8366_mib_counter rtl8366s_mib_counters[] = {
  138. { 0, 0, 4, "IfInOctets" },
  139. { 0, 4, 4, "EtherStatsOctets" },
  140. { 0, 8, 2, "EtherStatsUnderSizePkts" },
  141. { 0, 10, 2, "EtherFragments" },
  142. { 0, 12, 2, "EtherStatsPkts64Octets" },
  143. { 0, 14, 2, "EtherStatsPkts65to127Octets" },
  144. { 0, 16, 2, "EtherStatsPkts128to255Octets" },
  145. { 0, 18, 2, "EtherStatsPkts256to511Octets" },
  146. { 0, 20, 2, "EtherStatsPkts512to1023Octets" },
  147. { 0, 22, 2, "EtherStatsPkts1024to1518Octets" },
  148. { 0, 24, 2, "EtherOversizeStats" },
  149. { 0, 26, 2, "EtherStatsJabbers" },
  150. { 0, 28, 2, "IfInUcastPkts" },
  151. { 0, 30, 2, "EtherStatsMulticastPkts" },
  152. { 0, 32, 2, "EtherStatsBroadcastPkts" },
  153. { 0, 34, 2, "EtherStatsDropEvents" },
  154. { 0, 36, 2, "Dot3StatsFCSErrors" },
  155. { 0, 38, 2, "Dot3StatsSymbolErrors" },
  156. { 0, 40, 2, "Dot3InPauseFrames" },
  157. { 0, 42, 2, "Dot3ControlInUnknownOpcodes" },
  158. { 0, 44, 4, "IfOutOctets" },
  159. { 0, 48, 2, "Dot3StatsSingleCollisionFrames" },
  160. { 0, 50, 2, "Dot3StatMultipleCollisionFrames" },
  161. { 0, 52, 2, "Dot3sDeferredTransmissions" },
  162. { 0, 54, 2, "Dot3StatsLateCollisions" },
  163. { 0, 56, 2, "EtherStatsCollisions" },
  164. { 0, 58, 2, "Dot3StatsExcessiveCollisions" },
  165. { 0, 60, 2, "Dot3OutPauseFrames" },
  166. { 0, 62, 2, "Dot1dBasePortDelayExceededDiscards" },
  167. /*
  168. * The following counters are accessible at a different
  169. * base address.
  170. */
  171. { 1, 0, 2, "Dot1dTpPortInDiscards" },
  172. { 1, 2, 2, "IfOutUcastPkts" },
  173. { 1, 4, 2, "IfOutMulticastPkts" },
  174. { 1, 6, 2, "IfOutBroadcastPkts" },
  175. };
  176. #define REG_WR(_smi, _reg, _val) \
  177. do { \
  178. err = rtl8366_smi_write_reg(_smi, _reg, _val); \
  179. if (err) \
  180. return err; \
  181. } while (0)
  182. #define REG_RMW(_smi, _reg, _mask, _val) \
  183. do { \
  184. err = rtl8366_smi_rmwr(_smi, _reg, _mask, _val); \
  185. if (err) \
  186. return err; \
  187. } while (0)
  188. static int rtl8366s_reset_chip(struct rtl8366_smi *smi)
  189. {
  190. int timeout = 10;
  191. u32 data;
  192. rtl8366_smi_write_reg(smi, RTL8366S_RESET_CTRL_REG,
  193. RTL8366S_CHIP_CTRL_RESET_HW);
  194. do {
  195. msleep(1);
  196. if (rtl8366_smi_read_reg(smi, RTL8366S_RESET_CTRL_REG, &data))
  197. return -EIO;
  198. if (!(data & RTL8366S_CHIP_CTRL_RESET_HW))
  199. break;
  200. } while (--timeout);
  201. if (!timeout) {
  202. printk("Timeout waiting for the switch to reset\n");
  203. return -EIO;
  204. }
  205. return 0;
  206. }
  207. static int rtl8366s_hw_init(struct rtl8366_smi *smi)
  208. {
  209. int err;
  210. /* set maximum packet length to 1536 bytes */
  211. REG_RMW(smi, RTL8366S_SGCR, RTL8366S_SGCR_MAX_LENGTH_MASK,
  212. RTL8366S_SGCR_MAX_LENGTH_1536);
  213. /* enable all ports */
  214. REG_WR(smi, RTL8366S_PECR, 0);
  215. /* enable learning for all ports */
  216. REG_WR(smi, RTL8366S_SSCR0, 0);
  217. /* enable auto ageing for all ports */
  218. REG_WR(smi, RTL8366S_SSCR1, 0);
  219. /*
  220. * discard VLAN tagged packets if the port is not a member of
  221. * the VLAN with which the packets is associated.
  222. */
  223. REG_WR(smi, RTL8366S_VLAN_MEMBERINGRESS_REG, RTL8366S_PORT_ALL);
  224. /* don't drop packets whose DA has not been learned */
  225. REG_RMW(smi, RTL8366S_SSCR2, RTL8366S_SSCR2_DROP_UNKNOWN_DA, 0);
  226. return 0;
  227. }
  228. static int rtl8366s_read_phy_reg(struct rtl8366_smi *smi,
  229. u32 phy_no, u32 page, u32 addr, u32 *data)
  230. {
  231. u32 reg;
  232. int ret;
  233. if (phy_no > RTL8366S_PHY_NO_MAX)
  234. return -EINVAL;
  235. if (page > RTL8366S_PHY_PAGE_MAX)
  236. return -EINVAL;
  237. if (addr > RTL8366S_PHY_ADDR_MAX)
  238. return -EINVAL;
  239. ret = rtl8366_smi_write_reg(smi, RTL8366S_PHY_ACCESS_CTRL_REG,
  240. RTL8366S_PHY_CTRL_READ);
  241. if (ret)
  242. return ret;
  243. reg = 0x8000 | (1 << (phy_no + RTL8366S_PHY_NO_OFFSET)) |
  244. ((page << RTL8366S_PHY_PAGE_OFFSET) & RTL8366S_PHY_PAGE_MASK) |
  245. (addr & RTL8366S_PHY_REG_MASK);
  246. ret = rtl8366_smi_write_reg(smi, reg, 0);
  247. if (ret)
  248. return ret;
  249. ret = rtl8366_smi_read_reg(smi, RTL8366S_PHY_ACCESS_DATA_REG, data);
  250. if (ret)
  251. return ret;
  252. return 0;
  253. }
  254. static int rtl8366s_write_phy_reg(struct rtl8366_smi *smi,
  255. u32 phy_no, u32 page, u32 addr, u32 data)
  256. {
  257. u32 reg;
  258. int ret;
  259. if (phy_no > RTL8366S_PHY_NO_MAX)
  260. return -EINVAL;
  261. if (page > RTL8366S_PHY_PAGE_MAX)
  262. return -EINVAL;
  263. if (addr > RTL8366S_PHY_ADDR_MAX)
  264. return -EINVAL;
  265. ret = rtl8366_smi_write_reg(smi, RTL8366S_PHY_ACCESS_CTRL_REG,
  266. RTL8366S_PHY_CTRL_WRITE);
  267. if (ret)
  268. return ret;
  269. reg = 0x8000 | (1 << (phy_no + RTL8366S_PHY_NO_OFFSET)) |
  270. ((page << RTL8366S_PHY_PAGE_OFFSET) & RTL8366S_PHY_PAGE_MASK) |
  271. (addr & RTL8366S_PHY_REG_MASK);
  272. ret = rtl8366_smi_write_reg(smi, reg, data);
  273. if (ret)
  274. return ret;
  275. return 0;
  276. }
  277. static int rtl8366_get_mib_counter(struct rtl8366_smi *smi, int counter,
  278. int port, unsigned long long *val)
  279. {
  280. int i;
  281. int err;
  282. u32 addr, data;
  283. u64 mibvalue;
  284. if (port > RTL8366S_NUM_PORTS || counter >= RTL8366S_MIB_COUNT)
  285. return -EINVAL;
  286. switch (rtl8366s_mib_counters[counter].base) {
  287. case 0:
  288. addr = RTL8366S_MIB_COUNTER_BASE +
  289. RTL8366S_MIB_COUNTER_PORT_OFFSET * port;
  290. break;
  291. case 1:
  292. addr = RTL8366S_MIB_COUNTER_BASE2 +
  293. RTL8366S_MIB_COUNTER_PORT_OFFSET2 * port;
  294. break;
  295. default:
  296. return -EINVAL;
  297. }
  298. addr += rtl8366s_mib_counters[counter].offset;
  299. /*
  300. * Writing access counter address first
  301. * then ASIC will prepare 64bits counter wait for being retrived
  302. */
  303. data = 0; /* writing data will be discard by ASIC */
  304. err = rtl8366_smi_write_reg(smi, addr, data);
  305. if (err)
  306. return err;
  307. /* read MIB control register */
  308. err = rtl8366_smi_read_reg(smi, RTL8366S_MIB_CTRL_REG, &data);
  309. if (err)
  310. return err;
  311. if (data & RTL8366S_MIB_CTRL_BUSY_MASK)
  312. return -EBUSY;
  313. if (data & RTL8366S_MIB_CTRL_RESET_MASK)
  314. return -EIO;
  315. mibvalue = 0;
  316. for (i = rtl8366s_mib_counters[counter].length; i > 0; i--) {
  317. err = rtl8366_smi_read_reg(smi, addr + (i - 1), &data);
  318. if (err)
  319. return err;
  320. mibvalue = (mibvalue << 16) | (data & 0xFFFF);
  321. }
  322. *val = mibvalue;
  323. return 0;
  324. }
  325. static int rtl8366s_get_vlan_4k(struct rtl8366_smi *smi, u32 vid,
  326. struct rtl8366_vlan_4k *vlan4k)
  327. {
  328. u32 data[2];
  329. int err;
  330. int i;
  331. memset(vlan4k, '\0', sizeof(struct rtl8366_vlan_4k));
  332. if (vid >= RTL8366S_NUM_VIDS)
  333. return -EINVAL;
  334. /* write VID */
  335. err = rtl8366_smi_write_reg(smi, RTL8366S_VLAN_TABLE_WRITE_BASE,
  336. vid & RTL8366S_VLAN_VID_MASK);
  337. if (err)
  338. return err;
  339. /* write table access control word */
  340. err = rtl8366_smi_write_reg(smi, RTL8366S_TABLE_ACCESS_CTRL_REG,
  341. RTL8366S_TABLE_VLAN_READ_CTRL);
  342. if (err)
  343. return err;
  344. for (i = 0; i < 2; i++) {
  345. err = rtl8366_smi_read_reg(smi,
  346. RTL8366S_VLAN_TABLE_READ_BASE + i,
  347. &data[i]);
  348. if (err)
  349. return err;
  350. }
  351. vlan4k->vid = vid;
  352. vlan4k->untag = (data[1] >> RTL8366S_VLAN_UNTAG_SHIFT) &
  353. RTL8366S_VLAN_UNTAG_MASK;
  354. vlan4k->member = data[1] & RTL8366S_VLAN_MEMBER_MASK;
  355. vlan4k->fid = (data[1] >> RTL8366S_VLAN_FID_SHIFT) &
  356. RTL8366S_VLAN_FID_MASK;
  357. return 0;
  358. }
  359. static int rtl8366s_set_vlan_4k(struct rtl8366_smi *smi,
  360. const struct rtl8366_vlan_4k *vlan4k)
  361. {
  362. u32 data[2];
  363. int err;
  364. int i;
  365. if (vlan4k->vid >= RTL8366S_NUM_VIDS ||
  366. vlan4k->member > RTL8366S_PORT_ALL ||
  367. vlan4k->untag > RTL8366S_PORT_ALL ||
  368. vlan4k->fid > RTL8366S_FIDMAX)
  369. return -EINVAL;
  370. data[0] = vlan4k->vid & RTL8366S_VLAN_VID_MASK;
  371. data[1] = (vlan4k->member & RTL8366S_VLAN_MEMBER_MASK) |
  372. ((vlan4k->untag & RTL8366S_VLAN_UNTAG_MASK) <<
  373. RTL8366S_VLAN_UNTAG_SHIFT) |
  374. ((vlan4k->fid & RTL8366S_VLAN_FID_MASK) <<
  375. RTL8366S_VLAN_FID_SHIFT);
  376. for (i = 0; i < 2; i++) {
  377. err = rtl8366_smi_write_reg(smi,
  378. RTL8366S_VLAN_TABLE_WRITE_BASE + i,
  379. data[i]);
  380. if (err)
  381. return err;
  382. }
  383. /* write table access control word */
  384. err = rtl8366_smi_write_reg(smi, RTL8366S_TABLE_ACCESS_CTRL_REG,
  385. RTL8366S_TABLE_VLAN_WRITE_CTRL);
  386. return err;
  387. }
  388. static int rtl8366s_get_vlan_mc(struct rtl8366_smi *smi, u32 index,
  389. struct rtl8366_vlan_mc *vlanmc)
  390. {
  391. u32 data[2];
  392. int err;
  393. int i;
  394. memset(vlanmc, '\0', sizeof(struct rtl8366_vlan_mc));
  395. if (index >= RTL8366S_NUM_VLANS)
  396. return -EINVAL;
  397. for (i = 0; i < 2; i++) {
  398. err = rtl8366_smi_read_reg(smi,
  399. RTL8366S_VLAN_MC_BASE(index) + i,
  400. &data[i]);
  401. if (err)
  402. return err;
  403. }
  404. vlanmc->vid = data[0] & RTL8366S_VLAN_VID_MASK;
  405. vlanmc->priority = (data[0] >> RTL8366S_VLAN_PRIORITY_SHIFT) &
  406. RTL8366S_VLAN_PRIORITY_MASK;
  407. vlanmc->untag = (data[1] >> RTL8366S_VLAN_UNTAG_SHIFT) &
  408. RTL8366S_VLAN_UNTAG_MASK;
  409. vlanmc->member = data[1] & RTL8366S_VLAN_MEMBER_MASK;
  410. vlanmc->fid = (data[1] >> RTL8366S_VLAN_FID_SHIFT) &
  411. RTL8366S_VLAN_FID_MASK;
  412. return 0;
  413. }
  414. static int rtl8366s_set_vlan_mc(struct rtl8366_smi *smi, u32 index,
  415. const struct rtl8366_vlan_mc *vlanmc)
  416. {
  417. u32 data[2];
  418. int err;
  419. int i;
  420. if (index >= RTL8366S_NUM_VLANS ||
  421. vlanmc->vid >= RTL8366S_NUM_VIDS ||
  422. vlanmc->priority > RTL8366S_PRIORITYMAX ||
  423. vlanmc->member > RTL8366S_PORT_ALL ||
  424. vlanmc->untag > RTL8366S_PORT_ALL ||
  425. vlanmc->fid > RTL8366S_FIDMAX)
  426. return -EINVAL;
  427. data[0] = (vlanmc->vid & RTL8366S_VLAN_VID_MASK) |
  428. ((vlanmc->priority & RTL8366S_VLAN_PRIORITY_MASK) <<
  429. RTL8366S_VLAN_PRIORITY_SHIFT);
  430. data[1] = (vlanmc->member & RTL8366S_VLAN_MEMBER_MASK) |
  431. ((vlanmc->untag & RTL8366S_VLAN_UNTAG_MASK) <<
  432. RTL8366S_VLAN_UNTAG_SHIFT) |
  433. ((vlanmc->fid & RTL8366S_VLAN_FID_MASK) <<
  434. RTL8366S_VLAN_FID_SHIFT);
  435. for (i = 0; i < 2; i++) {
  436. err = rtl8366_smi_write_reg(smi,
  437. RTL8366S_VLAN_MC_BASE(index) + i,
  438. data[i]);
  439. if (err)
  440. return err;
  441. }
  442. return 0;
  443. }
  444. static int rtl8366s_get_mc_index(struct rtl8366_smi *smi, int port, int *val)
  445. {
  446. u32 data;
  447. int err;
  448. if (port >= RTL8366S_NUM_PORTS)
  449. return -EINVAL;
  450. err = rtl8366_smi_read_reg(smi, RTL8366S_PORT_VLAN_CTRL_REG(port),
  451. &data);
  452. if (err)
  453. return err;
  454. *val = (data >> RTL8366S_PORT_VLAN_CTRL_SHIFT(port)) &
  455. RTL8366S_PORT_VLAN_CTRL_MASK;
  456. return 0;
  457. }
  458. static int rtl8366s_set_mc_index(struct rtl8366_smi *smi, int port, int index)
  459. {
  460. if (port >= RTL8366S_NUM_PORTS || index >= RTL8366S_NUM_VLANS)
  461. return -EINVAL;
  462. return rtl8366_smi_rmwr(smi, RTL8366S_PORT_VLAN_CTRL_REG(port),
  463. RTL8366S_PORT_VLAN_CTRL_MASK <<
  464. RTL8366S_PORT_VLAN_CTRL_SHIFT(port),
  465. (index & RTL8366S_PORT_VLAN_CTRL_MASK) <<
  466. RTL8366S_PORT_VLAN_CTRL_SHIFT(port));
  467. }
  468. static int rtl8366s_enable_vlan(struct rtl8366_smi *smi, int enable)
  469. {
  470. return rtl8366_smi_rmwr(smi, RTL8366S_SGCR, RTL8366S_SGCR_EN_VLAN,
  471. (enable) ? RTL8366S_SGCR_EN_VLAN : 0);
  472. }
  473. static int rtl8366s_enable_vlan4k(struct rtl8366_smi *smi, int enable)
  474. {
  475. return rtl8366_smi_rmwr(smi, RTL8366S_VLAN_TB_CTRL_REG,
  476. 1, (enable) ? 1 : 0);
  477. }
  478. static int rtl8366s_is_vlan_valid(struct rtl8366_smi *smi, unsigned vlan)
  479. {
  480. unsigned max = RTL8366S_NUM_VLANS;
  481. if (smi->vlan4k_enabled)
  482. max = RTL8366S_NUM_VIDS - 1;
  483. if (vlan == 0 || vlan >= max)
  484. return 0;
  485. return 1;
  486. }
  487. static int rtl8366s_sw_reset_mibs(struct switch_dev *dev,
  488. const struct switch_attr *attr,
  489. struct switch_val *val)
  490. {
  491. struct rtl8366_smi *smi = sw_to_rtl8366_smi(dev);
  492. return rtl8366_smi_rmwr(smi, RTL8366S_MIB_CTRL_REG, 0, (1 << 2));
  493. }
  494. static int rtl8366s_sw_get_blinkrate(struct switch_dev *dev,
  495. const struct switch_attr *attr,
  496. struct switch_val *val)
  497. {
  498. struct rtl8366_smi *smi = sw_to_rtl8366_smi(dev);
  499. u32 data;
  500. rtl8366_smi_read_reg(smi, RTL8366S_LED_BLINKRATE_REG, &data);
  501. val->value.i = (data & (RTL8366S_LED_BLINKRATE_MASK));
  502. return 0;
  503. }
  504. static int rtl8366s_sw_set_blinkrate(struct switch_dev *dev,
  505. const struct switch_attr *attr,
  506. struct switch_val *val)
  507. {
  508. struct rtl8366_smi *smi = sw_to_rtl8366_smi(dev);
  509. if (val->value.i >= 6)
  510. return -EINVAL;
  511. return rtl8366_smi_rmwr(smi, RTL8366S_LED_BLINKRATE_REG,
  512. RTL8366S_LED_BLINKRATE_MASK,
  513. val->value.i);
  514. }
  515. static int rtl8366s_sw_get_learning_enable(struct switch_dev *dev,
  516. const struct switch_attr *attr,
  517. struct switch_val *val)
  518. {
  519. struct rtl8366_smi *smi = sw_to_rtl8366_smi(dev);
  520. u32 data;
  521. rtl8366_smi_read_reg(smi,RTL8366S_SSCR0, &data);
  522. val->value.i = !data;
  523. return 0;
  524. }
  525. static int rtl8366s_sw_set_learning_enable(struct switch_dev *dev,
  526. const struct switch_attr *attr,
  527. struct switch_val *val)
  528. {
  529. struct rtl8366_smi *smi = sw_to_rtl8366_smi(dev);
  530. u32 portmask = 0;
  531. int err = 0;
  532. if (!val->value.i)
  533. portmask = RTL8366S_PORT_ALL;
  534. /* set learning for all ports */
  535. REG_WR(smi, RTL8366S_SSCR0, portmask);
  536. /* set auto ageing for all ports */
  537. REG_WR(smi, RTL8366S_SSCR1, portmask);
  538. return 0;
  539. }
  540. static const char *rtl8366s_speed_str(unsigned speed)
  541. {
  542. switch (speed) {
  543. case 0:
  544. return "10baseT";
  545. case 1:
  546. return "100baseT";
  547. case 2:
  548. return "1000baseT";
  549. }
  550. return "unknown";
  551. }
  552. static int rtl8366s_sw_get_port_link(struct switch_dev *dev,
  553. const struct switch_attr *attr,
  554. struct switch_val *val)
  555. {
  556. struct rtl8366_smi *smi = sw_to_rtl8366_smi(dev);
  557. u32 len = 0, data = 0;
  558. if (val->port_vlan >= RTL8366S_NUM_PORTS)
  559. return -EINVAL;
  560. memset(smi->buf, '\0', sizeof(smi->buf));
  561. rtl8366_smi_read_reg(smi, RTL8366S_PORT_LINK_STATUS_BASE +
  562. (val->port_vlan / 2), &data);
  563. if (val->port_vlan % 2)
  564. data = data >> 8;
  565. if (data & RTL8366S_PORT_STATUS_LINK_MASK) {
  566. len = snprintf(smi->buf, sizeof(smi->buf),
  567. "port:%d link:up speed:%s %s-duplex %s%s%s",
  568. val->port_vlan,
  569. rtl8366s_speed_str(data &
  570. RTL8366S_PORT_STATUS_SPEED_MASK),
  571. (data & RTL8366S_PORT_STATUS_DUPLEX_MASK) ?
  572. "full" : "half",
  573. (data & RTL8366S_PORT_STATUS_TXPAUSE_MASK) ?
  574. "tx-pause ": "",
  575. (data & RTL8366S_PORT_STATUS_RXPAUSE_MASK) ?
  576. "rx-pause " : "",
  577. (data & RTL8366S_PORT_STATUS_AN_MASK) ?
  578. "nway ": "");
  579. } else {
  580. len = snprintf(smi->buf, sizeof(smi->buf), "port:%d link: down",
  581. val->port_vlan);
  582. }
  583. val->value.s = smi->buf;
  584. val->len = len;
  585. return 0;
  586. }
  587. static int rtl8366s_sw_set_port_led(struct switch_dev *dev,
  588. const struct switch_attr *attr,
  589. struct switch_val *val)
  590. {
  591. struct rtl8366_smi *smi = sw_to_rtl8366_smi(dev);
  592. u32 data;
  593. u32 mask;
  594. u32 reg;
  595. if (val->port_vlan >= RTL8366S_NUM_PORTS ||
  596. (1 << val->port_vlan) == RTL8366S_PORT_UNKNOWN)
  597. return -EINVAL;
  598. if (val->port_vlan == RTL8366S_PORT_NUM_CPU) {
  599. reg = RTL8366S_LED_BLINKRATE_REG;
  600. mask = 0xF << 4;
  601. data = val->value.i << 4;
  602. } else {
  603. reg = RTL8366S_LED_CTRL_REG;
  604. mask = 0xF << (val->port_vlan * 4),
  605. data = val->value.i << (val->port_vlan * 4);
  606. }
  607. return rtl8366_smi_rmwr(smi, reg, mask, data);
  608. }
  609. static int rtl8366s_sw_get_port_led(struct switch_dev *dev,
  610. const struct switch_attr *attr,
  611. struct switch_val *val)
  612. {
  613. struct rtl8366_smi *smi = sw_to_rtl8366_smi(dev);
  614. u32 data = 0;
  615. if (val->port_vlan >= RTL8366S_NUM_LEDGROUPS)
  616. return -EINVAL;
  617. rtl8366_smi_read_reg(smi, RTL8366S_LED_CTRL_REG, &data);
  618. val->value.i = (data >> (val->port_vlan * 4)) & 0x000F;
  619. return 0;
  620. }
  621. static int rtl8366s_sw_reset_port_mibs(struct switch_dev *dev,
  622. const struct switch_attr *attr,
  623. struct switch_val *val)
  624. {
  625. struct rtl8366_smi *smi = sw_to_rtl8366_smi(dev);
  626. if (val->port_vlan >= RTL8366S_NUM_PORTS)
  627. return -EINVAL;
  628. return rtl8366_smi_rmwr(smi, RTL8366S_MIB_CTRL_REG,
  629. 0, (1 << (val->port_vlan + 3)));
  630. }
  631. static int rtl8366s_sw_reset_switch(struct switch_dev *dev)
  632. {
  633. struct rtl8366_smi *smi = sw_to_rtl8366_smi(dev);
  634. int err;
  635. err = rtl8366s_reset_chip(smi);
  636. if (err)
  637. return err;
  638. err = rtl8366s_hw_init(smi);
  639. if (err)
  640. return err;
  641. return rtl8366_reset_vlan(smi);
  642. }
  643. static struct switch_attr rtl8366s_globals[] = {
  644. {
  645. .type = SWITCH_TYPE_INT,
  646. .name = "enable_learning",
  647. .description = "Enable learning, enable aging",
  648. .set = rtl8366s_sw_set_learning_enable,
  649. .get = rtl8366s_sw_get_learning_enable,
  650. .max = 1,
  651. }, {
  652. .type = SWITCH_TYPE_INT,
  653. .name = "enable_vlan",
  654. .description = "Enable VLAN mode",
  655. .set = rtl8366_sw_set_vlan_enable,
  656. .get = rtl8366_sw_get_vlan_enable,
  657. .max = 1,
  658. .ofs = 1
  659. }, {
  660. .type = SWITCH_TYPE_INT,
  661. .name = "enable_vlan4k",
  662. .description = "Enable VLAN 4K mode",
  663. .set = rtl8366_sw_set_vlan_enable,
  664. .get = rtl8366_sw_get_vlan_enable,
  665. .max = 1,
  666. .ofs = 2
  667. }, {
  668. .type = SWITCH_TYPE_NOVAL,
  669. .name = "reset_mibs",
  670. .description = "Reset all MIB counters",
  671. .set = rtl8366s_sw_reset_mibs,
  672. }, {
  673. .type = SWITCH_TYPE_INT,
  674. .name = "blinkrate",
  675. .description = "Get/Set LED blinking rate (0 = 43ms, 1 = 84ms,"
  676. " 2 = 120ms, 3 = 170ms, 4 = 340ms, 5 = 670ms)",
  677. .set = rtl8366s_sw_set_blinkrate,
  678. .get = rtl8366s_sw_get_blinkrate,
  679. .max = 5
  680. },
  681. };
  682. static struct switch_attr rtl8366s_port[] = {
  683. {
  684. .type = SWITCH_TYPE_STRING,
  685. .name = "link",
  686. .description = "Get port link information",
  687. .max = 1,
  688. .set = NULL,
  689. .get = rtl8366s_sw_get_port_link,
  690. }, {
  691. .type = SWITCH_TYPE_NOVAL,
  692. .name = "reset_mib",
  693. .description = "Reset single port MIB counters",
  694. .set = rtl8366s_sw_reset_port_mibs,
  695. }, {
  696. .type = SWITCH_TYPE_STRING,
  697. .name = "mib",
  698. .description = "Get MIB counters for port",
  699. .max = 33,
  700. .set = NULL,
  701. .get = rtl8366_sw_get_port_mib,
  702. }, {
  703. .type = SWITCH_TYPE_INT,
  704. .name = "led",
  705. .description = "Get/Set port group (0 - 3) led mode (0 - 15)",
  706. .max = 15,
  707. .set = rtl8366s_sw_set_port_led,
  708. .get = rtl8366s_sw_get_port_led,
  709. },
  710. };
  711. static struct switch_attr rtl8366s_vlan[] = {
  712. {
  713. .type = SWITCH_TYPE_STRING,
  714. .name = "info",
  715. .description = "Get vlan information",
  716. .max = 1,
  717. .set = NULL,
  718. .get = rtl8366_sw_get_vlan_info,
  719. },
  720. };
  721. static const struct switch_dev_ops rtl8366_ops = {
  722. .attr_global = {
  723. .attr = rtl8366s_globals,
  724. .n_attr = ARRAY_SIZE(rtl8366s_globals),
  725. },
  726. .attr_port = {
  727. .attr = rtl8366s_port,
  728. .n_attr = ARRAY_SIZE(rtl8366s_port),
  729. },
  730. .attr_vlan = {
  731. .attr = rtl8366s_vlan,
  732. .n_attr = ARRAY_SIZE(rtl8366s_vlan),
  733. },
  734. .get_vlan_ports = rtl8366_sw_get_vlan_ports,
  735. .set_vlan_ports = rtl8366_sw_set_vlan_ports,
  736. .get_port_pvid = rtl8366_sw_get_port_pvid,
  737. .set_port_pvid = rtl8366_sw_set_port_pvid,
  738. .reset_switch = rtl8366s_sw_reset_switch,
  739. };
  740. static int rtl8366s_switch_init(struct rtl8366_smi *smi)
  741. {
  742. struct switch_dev *dev = &smi->sw_dev;
  743. int err;
  744. dev->name = "RTL8366S";
  745. dev->cpu_port = RTL8366S_PORT_NUM_CPU;
  746. dev->ports = RTL8366S_NUM_PORTS;
  747. dev->vlans = RTL8366S_NUM_VIDS;
  748. dev->ops = &rtl8366_ops;
  749. dev->devname = dev_name(smi->parent);
  750. err = register_switch(dev, NULL);
  751. if (err)
  752. dev_err(smi->parent, "switch registration failed\n");
  753. return err;
  754. }
  755. static void rtl8366s_switch_cleanup(struct rtl8366_smi *smi)
  756. {
  757. unregister_switch(&smi->sw_dev);
  758. }
  759. static int rtl8366s_mii_read(struct mii_bus *bus, int addr, int reg)
  760. {
  761. struct rtl8366_smi *smi = bus->priv;
  762. u32 val = 0;
  763. int err;
  764. err = rtl8366s_read_phy_reg(smi, addr, 0, reg, &val);
  765. if (err)
  766. return 0xffff;
  767. return val;
  768. }
  769. static int rtl8366s_mii_write(struct mii_bus *bus, int addr, int reg, u16 val)
  770. {
  771. struct rtl8366_smi *smi = bus->priv;
  772. u32 t;
  773. int err;
  774. err = rtl8366s_write_phy_reg(smi, addr, 0, reg, val);
  775. /* flush write */
  776. (void) rtl8366s_read_phy_reg(smi, addr, 0, reg, &t);
  777. return err;
  778. }
  779. static int rtl8366s_mii_bus_match(struct mii_bus *bus)
  780. {
  781. return (bus->read == rtl8366s_mii_read &&
  782. bus->write == rtl8366s_mii_write);
  783. }
  784. static int rtl8366s_setup(struct rtl8366_smi *smi)
  785. {
  786. int ret;
  787. ret = rtl8366s_reset_chip(smi);
  788. if (ret)
  789. return ret;
  790. ret = rtl8366s_hw_init(smi);
  791. return ret;
  792. }
  793. static int rtl8366s_detect(struct rtl8366_smi *smi)
  794. {
  795. u32 chip_id = 0;
  796. u32 chip_ver = 0;
  797. int ret;
  798. ret = rtl8366_smi_read_reg(smi, RTL8366S_CHIP_ID_REG, &chip_id);
  799. if (ret) {
  800. dev_err(smi->parent, "unable to read chip id\n");
  801. return ret;
  802. }
  803. switch (chip_id) {
  804. case RTL8366S_CHIP_ID_8366:
  805. break;
  806. default:
  807. dev_err(smi->parent, "unknown chip id (%04x)\n", chip_id);
  808. return -ENODEV;
  809. }
  810. ret = rtl8366_smi_read_reg(smi, RTL8366S_CHIP_VERSION_CTRL_REG,
  811. &chip_ver);
  812. if (ret) {
  813. dev_err(smi->parent, "unable to read chip version\n");
  814. return ret;
  815. }
  816. dev_info(smi->parent, "RTL%04x ver. %u chip found\n",
  817. chip_id, chip_ver & RTL8366S_CHIP_VERSION_MASK);
  818. return 0;
  819. }
  820. static struct rtl8366_smi_ops rtl8366s_smi_ops = {
  821. .detect = rtl8366s_detect,
  822. .setup = rtl8366s_setup,
  823. .mii_read = rtl8366s_mii_read,
  824. .mii_write = rtl8366s_mii_write,
  825. .get_vlan_mc = rtl8366s_get_vlan_mc,
  826. .set_vlan_mc = rtl8366s_set_vlan_mc,
  827. .get_vlan_4k = rtl8366s_get_vlan_4k,
  828. .set_vlan_4k = rtl8366s_set_vlan_4k,
  829. .get_mc_index = rtl8366s_get_mc_index,
  830. .set_mc_index = rtl8366s_set_mc_index,
  831. .get_mib_counter = rtl8366_get_mib_counter,
  832. .is_vlan_valid = rtl8366s_is_vlan_valid,
  833. .enable_vlan = rtl8366s_enable_vlan,
  834. .enable_vlan4k = rtl8366s_enable_vlan4k,
  835. };
  836. static int __devinit rtl8366s_probe(struct platform_device *pdev)
  837. {
  838. static int rtl8366_smi_version_printed;
  839. struct rtl8366s_platform_data *pdata;
  840. struct rtl8366_smi *smi;
  841. int err;
  842. if (!rtl8366_smi_version_printed++)
  843. printk(KERN_NOTICE RTL8366S_DRIVER_DESC
  844. " version " RTL8366S_DRIVER_VER"\n");
  845. pdata = pdev->dev.platform_data;
  846. if (!pdata) {
  847. dev_err(&pdev->dev, "no platform data specified\n");
  848. err = -EINVAL;
  849. goto err_out;
  850. }
  851. smi = rtl8366_smi_alloc(&pdev->dev);
  852. if (!smi) {
  853. err = -ENOMEM;
  854. goto err_out;
  855. }
  856. smi->gpio_sda = pdata->gpio_sda;
  857. smi->gpio_sck = pdata->gpio_sck;
  858. smi->ops = &rtl8366s_smi_ops;
  859. smi->cpu_port = RTL8366S_PORT_NUM_CPU;
  860. smi->num_ports = RTL8366S_NUM_PORTS;
  861. smi->num_vlan_mc = RTL8366S_NUM_VLANS;
  862. smi->mib_counters = rtl8366s_mib_counters;
  863. smi->num_mib_counters = ARRAY_SIZE(rtl8366s_mib_counters);
  864. err = rtl8366_smi_init(smi);
  865. if (err)
  866. goto err_free_smi;
  867. platform_set_drvdata(pdev, smi);
  868. err = rtl8366s_switch_init(smi);
  869. if (err)
  870. goto err_clear_drvdata;
  871. return 0;
  872. err_clear_drvdata:
  873. platform_set_drvdata(pdev, NULL);
  874. rtl8366_smi_cleanup(smi);
  875. err_free_smi:
  876. kfree(smi);
  877. err_out:
  878. return err;
  879. }
  880. static int rtl8366s_phy_config_init(struct phy_device *phydev)
  881. {
  882. if (!rtl8366s_mii_bus_match(phydev->bus))
  883. return -EINVAL;
  884. return 0;
  885. }
  886. static int rtl8366s_phy_config_aneg(struct phy_device *phydev)
  887. {
  888. /* phy 4 might be connected to a second mac, allow aneg config */
  889. if (phydev->addr == RTL8366S_PHY_WAN)
  890. return genphy_config_aneg(phydev);
  891. return 0;
  892. }
  893. static struct phy_driver rtl8366s_phy_driver = {
  894. .phy_id = 0x001cc960,
  895. .name = "Realtek RTL8366S",
  896. .phy_id_mask = 0x1ffffff0,
  897. .features = PHY_GBIT_FEATURES,
  898. .config_aneg = rtl8366s_phy_config_aneg,
  899. .config_init = rtl8366s_phy_config_init,
  900. .read_status = genphy_read_status,
  901. .driver = {
  902. .owner = THIS_MODULE,
  903. },
  904. };
  905. static int __devexit rtl8366s_remove(struct platform_device *pdev)
  906. {
  907. struct rtl8366_smi *smi = platform_get_drvdata(pdev);
  908. if (smi) {
  909. rtl8366s_switch_cleanup(smi);
  910. platform_set_drvdata(pdev, NULL);
  911. rtl8366_smi_cleanup(smi);
  912. kfree(smi);
  913. }
  914. return 0;
  915. }
  916. static struct platform_driver rtl8366s_driver = {
  917. .driver = {
  918. .name = RTL8366S_DRIVER_NAME,
  919. .owner = THIS_MODULE,
  920. },
  921. .probe = rtl8366s_probe,
  922. .remove = __devexit_p(rtl8366s_remove),
  923. };
  924. static int __init rtl8366s_module_init(void)
  925. {
  926. int ret;
  927. ret = platform_driver_register(&rtl8366s_driver);
  928. if (ret)
  929. return ret;
  930. ret = phy_driver_register(&rtl8366s_phy_driver);
  931. if (ret)
  932. goto err_platform_unregister;
  933. return 0;
  934. err_platform_unregister:
  935. platform_driver_unregister(&rtl8366s_driver);
  936. return ret;
  937. }
  938. module_init(rtl8366s_module_init);
  939. static void __exit rtl8366s_module_exit(void)
  940. {
  941. phy_driver_unregister(&rtl8366s_phy_driver);
  942. platform_driver_unregister(&rtl8366s_driver);
  943. }
  944. module_exit(rtl8366s_module_exit);
  945. MODULE_DESCRIPTION(RTL8366S_DRIVER_DESC);
  946. MODULE_VERSION(RTL8366S_DRIVER_VER);
  947. MODULE_AUTHOR("Gabor Juhos <[email protected]>");
  948. MODULE_AUTHOR("Antti Seppälä <[email protected]>");
  949. MODULE_LICENSE("GPL v2");
  950. MODULE_ALIAS("platform:" RTL8366S_DRIVER_NAME);