psb6970.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443
  1. /*
  2. * Lantiq PSB6970 (Tantos) Switch driver
  3. *
  4. * Copyright (c) 2009,2010 Team Embedded.
  5. *
  6. * This program is free software; you can redistribute it and/or modify it
  7. * under the terms of the GNU General Public License v2 as published by the
  8. * Free Software Foundation.
  9. *
  10. * The switch programming done in this driver follows the
  11. * "Ethernet Traffic Separation using VLAN" Application Note as
  12. * published by Lantiq.
  13. */
  14. #include <linux/module.h>
  15. #include <linux/netdevice.h>
  16. #include <linux/switch.h>
  17. #include <linux/phy.h>
  18. #include <linux/version.h>
  19. #define PSB6970_MAX_VLANS 16
  20. #define PSB6970_NUM_PORTS 7
  21. #define PSB6970_DEFAULT_PORT_CPU 6
  22. #define PSB6970_IS_CPU_PORT(x) ((x) > 4)
  23. #define PHYADDR(_reg) ((_reg >> 5) & 0xff), (_reg & 0x1f)
  24. /* --- Identification --- */
  25. #define PSB6970_CI0 0x0100
  26. #define PSB6970_CI0_MASK 0x000f
  27. #define PSB6970_CI1 0x0101
  28. #define PSB6970_CI1_VAL 0x2599
  29. #define PSB6970_CI1_MASK 0xffff
  30. /* --- VLAN filter table --- */
  31. #define PSB6970_VFxL(i) ((i)*2+0x10) /* VLAN Filter Low */
  32. #define PSB6970_VFxL_VV (1 << 15) /* VLAN_Valid */
  33. #define PSB6970_VFxH(i) ((i)*2+0x11) /* VLAN Filter High */
  34. #define PSB6970_VFxH_TM_SHIFT 7 /* Tagged Member */
  35. /* --- Port registers --- */
  36. #define PSB6970_EC(p) ((p)*0x20+2) /* Extended Control */
  37. #define PSB6970_EC_IFNTE (1 << 1) /* Input Force No Tag Enable */
  38. #define PSB6970_PBVM(p) ((p)*0x20+3) /* Port Base VLAN Map */
  39. #define PSB6970_PBVM_VMCE (1 << 8)
  40. #define PSB6970_PBVM_AOVTP (1 << 9)
  41. #define PSB6970_PBVM_VSD (1 << 10)
  42. #define PSB6970_PBVM_VC (1 << 11) /* VID Check with VID table */
  43. #define PSB6970_PBVM_TBVE (1 << 13) /* Tag-Based VLAN enable */
  44. #define PSB6970_DVID(p) ((p)*0x20+4) /* Default VLAN ID & Priority */
  45. struct psb6970_priv {
  46. struct switch_dev dev;
  47. struct phy_device *phy;
  48. u16 (*read) (struct phy_device* phydev, int reg);
  49. void (*write) (struct phy_device* phydev, int reg, u16 val);
  50. struct mutex reg_mutex;
  51. /* all fields below are cleared on reset */
  52. struct_group(psb6970_priv_volatile,
  53. bool vlan;
  54. u16 vlan_id[PSB6970_MAX_VLANS];
  55. u8 vlan_table[PSB6970_MAX_VLANS];
  56. u8 vlan_tagged;
  57. u16 pvid[PSB6970_NUM_PORTS];
  58. );
  59. };
  60. #define to_psb6970(_dev) container_of(_dev, struct psb6970_priv, dev)
  61. static u16 psb6970_mii_read(struct phy_device *phydev, int reg)
  62. {
  63. struct mii_bus *bus = phydev->mdio.bus;
  64. return bus->read(bus, PHYADDR(reg));
  65. }
  66. static void psb6970_mii_write(struct phy_device *phydev, int reg, u16 val)
  67. {
  68. struct mii_bus *bus = phydev->mdio.bus;
  69. bus->write(bus, PHYADDR(reg), val);
  70. }
  71. static int
  72. psb6970_set_vlan(struct switch_dev *dev, const struct switch_attr *attr,
  73. struct switch_val *val)
  74. {
  75. struct psb6970_priv *priv = to_psb6970(dev);
  76. priv->vlan = !!val->value.i;
  77. return 0;
  78. }
  79. static int
  80. psb6970_get_vlan(struct switch_dev *dev, const struct switch_attr *attr,
  81. struct switch_val *val)
  82. {
  83. struct psb6970_priv *priv = to_psb6970(dev);
  84. val->value.i = priv->vlan;
  85. return 0;
  86. }
  87. static int psb6970_set_pvid(struct switch_dev *dev, int port, int vlan)
  88. {
  89. struct psb6970_priv *priv = to_psb6970(dev);
  90. /* make sure no invalid PVIDs get set */
  91. if (vlan >= dev->vlans)
  92. return -EINVAL;
  93. priv->pvid[port] = vlan;
  94. return 0;
  95. }
  96. static int psb6970_get_pvid(struct switch_dev *dev, int port, int *vlan)
  97. {
  98. struct psb6970_priv *priv = to_psb6970(dev);
  99. *vlan = priv->pvid[port];
  100. return 0;
  101. }
  102. static int
  103. psb6970_set_vid(struct switch_dev *dev, const struct switch_attr *attr,
  104. struct switch_val *val)
  105. {
  106. struct psb6970_priv *priv = to_psb6970(dev);
  107. priv->vlan_id[val->port_vlan] = val->value.i;
  108. return 0;
  109. }
  110. static int
  111. psb6970_get_vid(struct switch_dev *dev, const struct switch_attr *attr,
  112. struct switch_val *val)
  113. {
  114. struct psb6970_priv *priv = to_psb6970(dev);
  115. val->value.i = priv->vlan_id[val->port_vlan];
  116. return 0;
  117. }
  118. static struct switch_attr psb6970_globals[] = {
  119. {
  120. .type = SWITCH_TYPE_INT,
  121. .name = "enable_vlan",
  122. .description = "Enable VLAN mode",
  123. .set = psb6970_set_vlan,
  124. .get = psb6970_get_vlan,
  125. .max = 1},
  126. };
  127. static struct switch_attr psb6970_port[] = {
  128. };
  129. static struct switch_attr psb6970_vlan[] = {
  130. {
  131. .type = SWITCH_TYPE_INT,
  132. .name = "vid",
  133. .description = "VLAN ID (0-4094)",
  134. .set = psb6970_set_vid,
  135. .get = psb6970_get_vid,
  136. .max = 4094,
  137. },
  138. };
  139. static int psb6970_get_ports(struct switch_dev *dev, struct switch_val *val)
  140. {
  141. struct psb6970_priv *priv = to_psb6970(dev);
  142. u8 ports = priv->vlan_table[val->port_vlan];
  143. int i;
  144. val->len = 0;
  145. for (i = 0; i < PSB6970_NUM_PORTS; i++) {
  146. struct switch_port *p;
  147. if (!(ports & (1 << i)))
  148. continue;
  149. p = &val->value.ports[val->len++];
  150. p->id = i;
  151. if (priv->vlan_tagged & (1 << i))
  152. p->flags = (1 << SWITCH_PORT_FLAG_TAGGED);
  153. else
  154. p->flags = 0;
  155. }
  156. return 0;
  157. }
  158. static int psb6970_set_ports(struct switch_dev *dev, struct switch_val *val)
  159. {
  160. struct psb6970_priv *priv = to_psb6970(dev);
  161. u8 *vt = &priv->vlan_table[val->port_vlan];
  162. int i, j;
  163. *vt = 0;
  164. for (i = 0; i < val->len; i++) {
  165. struct switch_port *p = &val->value.ports[i];
  166. if (p->flags & (1 << SWITCH_PORT_FLAG_TAGGED))
  167. priv->vlan_tagged |= (1 << p->id);
  168. else {
  169. priv->vlan_tagged &= ~(1 << p->id);
  170. priv->pvid[p->id] = val->port_vlan;
  171. /* make sure that an untagged port does not
  172. * appear in other vlans */
  173. for (j = 0; j < PSB6970_MAX_VLANS; j++) {
  174. if (j == val->port_vlan)
  175. continue;
  176. priv->vlan_table[j] &= ~(1 << p->id);
  177. }
  178. }
  179. *vt |= 1 << p->id;
  180. }
  181. return 0;
  182. }
  183. static int psb6970_hw_apply(struct switch_dev *dev)
  184. {
  185. struct psb6970_priv *priv = to_psb6970(dev);
  186. int i, j;
  187. mutex_lock(&priv->reg_mutex);
  188. if (priv->vlan) {
  189. /* into the vlan translation unit */
  190. for (j = 0; j < PSB6970_MAX_VLANS; j++) {
  191. u8 vp = priv->vlan_table[j];
  192. if (vp) {
  193. priv->write(priv->phy, PSB6970_VFxL(j),
  194. PSB6970_VFxL_VV | priv->vlan_id[j]);
  195. priv->write(priv->phy, PSB6970_VFxH(j),
  196. ((vp & priv->
  197. vlan_tagged) <<
  198. PSB6970_VFxH_TM_SHIFT) | vp);
  199. } else /* clear VLAN Valid flag for unused vlans */
  200. priv->write(priv->phy, PSB6970_VFxL(j), 0);
  201. }
  202. }
  203. /* update the port destination mask registers and tag settings */
  204. for (i = 0; i < PSB6970_NUM_PORTS; i++) {
  205. int dvid = 1, pbvm = 0x7f | PSB6970_PBVM_VSD, ec = 0;
  206. if (priv->vlan) {
  207. ec = PSB6970_EC_IFNTE;
  208. dvid = priv->vlan_id[priv->pvid[i]];
  209. pbvm |= PSB6970_PBVM_TBVE | PSB6970_PBVM_VMCE;
  210. if ((i << 1) & priv->vlan_tagged)
  211. pbvm |= PSB6970_PBVM_AOVTP | PSB6970_PBVM_VC;
  212. }
  213. priv->write(priv->phy, PSB6970_PBVM(i), pbvm);
  214. if (!PSB6970_IS_CPU_PORT(i)) {
  215. priv->write(priv->phy, PSB6970_EC(i), ec);
  216. priv->write(priv->phy, PSB6970_DVID(i), dvid);
  217. }
  218. }
  219. mutex_unlock(&priv->reg_mutex);
  220. return 0;
  221. }
  222. static int psb6970_reset_switch(struct switch_dev *dev)
  223. {
  224. struct psb6970_priv *priv = to_psb6970(dev);
  225. int i;
  226. mutex_lock(&priv->reg_mutex);
  227. memset(&priv->psb6970_priv_volatile, 0,
  228. sizeof(priv->psb6970_priv_volatile));
  229. for (i = 0; i < PSB6970_MAX_VLANS; i++)
  230. priv->vlan_id[i] = i;
  231. mutex_unlock(&priv->reg_mutex);
  232. return psb6970_hw_apply(dev);
  233. }
  234. static const struct switch_dev_ops psb6970_ops = {
  235. .attr_global = {
  236. .attr = psb6970_globals,
  237. .n_attr = ARRAY_SIZE(psb6970_globals),
  238. },
  239. .attr_port = {
  240. .attr = psb6970_port,
  241. .n_attr = ARRAY_SIZE(psb6970_port),
  242. },
  243. .attr_vlan = {
  244. .attr = psb6970_vlan,
  245. .n_attr = ARRAY_SIZE(psb6970_vlan),
  246. },
  247. .get_port_pvid = psb6970_get_pvid,
  248. .set_port_pvid = psb6970_set_pvid,
  249. .get_vlan_ports = psb6970_get_ports,
  250. .set_vlan_ports = psb6970_set_ports,
  251. .apply_config = psb6970_hw_apply,
  252. .reset_switch = psb6970_reset_switch,
  253. };
  254. static int psb6970_config_init(struct phy_device *pdev)
  255. {
  256. struct psb6970_priv *priv;
  257. struct switch_dev *swdev;
  258. int ret;
  259. priv = kzalloc(sizeof(struct psb6970_priv), GFP_KERNEL);
  260. if (priv == NULL)
  261. return -ENOMEM;
  262. priv->phy = pdev;
  263. if (pdev->mdio.addr == 0)
  264. printk(KERN_INFO "%s: psb6970 switch driver attached.\n",
  265. pdev->attached_dev->name);
  266. if (pdev->mdio.addr != 0) {
  267. kfree(priv);
  268. return 0;
  269. }
  270. linkmode_zero(pdev->supported);
  271. linkmode_set_bit(ETHTOOL_LINK_MODE_100baseT_Full_BIT, pdev->supported);
  272. linkmode_copy(pdev->advertising, pdev->supported);
  273. mutex_init(&priv->reg_mutex);
  274. priv->read = psb6970_mii_read;
  275. priv->write = psb6970_mii_write;
  276. pdev->priv = priv;
  277. swdev = &priv->dev;
  278. swdev->cpu_port = PSB6970_DEFAULT_PORT_CPU;
  279. swdev->ops = &psb6970_ops;
  280. swdev->name = "Lantiq PSB6970";
  281. swdev->vlans = PSB6970_MAX_VLANS;
  282. swdev->ports = PSB6970_NUM_PORTS;
  283. if ((ret = register_switch(&priv->dev, pdev->attached_dev)) < 0) {
  284. kfree(priv);
  285. goto done;
  286. }
  287. ret = psb6970_reset_switch(&priv->dev);
  288. if (ret) {
  289. kfree(priv);
  290. goto done;
  291. }
  292. done:
  293. return ret;
  294. }
  295. static int psb6970_read_status(struct phy_device *phydev)
  296. {
  297. phydev->speed = SPEED_100;
  298. phydev->duplex = DUPLEX_FULL;
  299. phydev->link = 1;
  300. phydev->state = PHY_RUNNING;
  301. netif_carrier_on(phydev->attached_dev);
  302. phydev->adjust_link(phydev->attached_dev);
  303. return 0;
  304. }
  305. static int psb6970_config_aneg(struct phy_device *phydev)
  306. {
  307. return 0;
  308. }
  309. static int psb6970_probe(struct phy_device *pdev)
  310. {
  311. return 0;
  312. }
  313. static void psb6970_remove(struct phy_device *pdev)
  314. {
  315. struct psb6970_priv *priv = pdev->priv;
  316. if (!priv)
  317. return;
  318. if (pdev->mdio.addr == 0)
  319. unregister_switch(&priv->dev);
  320. kfree(priv);
  321. }
  322. static int psb6970_fixup(struct phy_device *dev)
  323. {
  324. struct mii_bus *bus = dev->mdio.bus;
  325. u16 reg;
  326. /* look for the switch on the bus */
  327. reg = bus->read(bus, PHYADDR(PSB6970_CI1)) & PSB6970_CI1_MASK;
  328. if (reg != PSB6970_CI1_VAL)
  329. return 0;
  330. dev->phy_id = (reg << 16);
  331. dev->phy_id |= bus->read(bus, PHYADDR(PSB6970_CI0)) & PSB6970_CI0_MASK;
  332. return 0;
  333. }
  334. static struct phy_driver psb6970_driver = {
  335. .name = "Lantiq PSB6970",
  336. .phy_id = PSB6970_CI1_VAL << 16,
  337. .phy_id_mask = 0xffff0000,
  338. .features = PHY_BASIC_FEATURES,
  339. .probe = psb6970_probe,
  340. .remove = psb6970_remove,
  341. .config_init = &psb6970_config_init,
  342. .config_aneg = &psb6970_config_aneg,
  343. .read_status = &psb6970_read_status,
  344. };
  345. int __init psb6970_init(void)
  346. {
  347. phy_register_fixup_for_id(PHY_ANY_ID, psb6970_fixup);
  348. return phy_driver_register(&psb6970_driver, THIS_MODULE);
  349. }
  350. module_init(psb6970_init);
  351. void __exit psb6970_exit(void)
  352. {
  353. phy_driver_unregister(&psb6970_driver);
  354. }
  355. module_exit(psb6970_exit);
  356. MODULE_DESCRIPTION("Lantiq PSB6970 Switch");
  357. MODULE_AUTHOR("Ithamar R. Adema <[email protected]>");
  358. MODULE_LICENSE("GPL");