712-mr33-essedma.patch 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340
  1. --- a/drivers/net/ethernet/qualcomm/essedma/edma_axi.c
  2. +++ b/drivers/net/ethernet/qualcomm/essedma/edma_axi.c
  3. @@ -17,6 +17,11 @@
  4. #include <linux/of.h>
  5. #include <linux/of_net.h>
  6. #include <linux/timer.h>
  7. +#include <linux/of_platform.h>
  8. +#include <linux/of_address.h>
  9. +#include <linux/clk.h>
  10. +#include <linux/string.h>
  11. +#include <linux/reset.h>
  12. #include "edma.h"
  13. #include "ess_edma.h"
  14. @@ -83,7 +88,103 @@ void edma_read_reg(u16 reg_addr, volatil
  15. *reg_value = readl((void __iomem *)(edma_hw_addr + reg_addr));
  16. }
  17. -/* edma_change_tx_coalesce()
  18. +static void ess_write_reg(struct edma_common_info *edma, u16 reg_addr, u32 reg_value)
  19. +{
  20. + writel(reg_value, ((void __iomem *)
  21. + ((unsigned long)edma->ess_hw_addr + reg_addr)));
  22. +}
  23. +
  24. +static void ess_read_reg(struct edma_common_info *edma, u16 reg_addr,
  25. + volatile u32 *reg_value)
  26. +{
  27. + *reg_value = readl((void __iomem *)
  28. + ((unsigned long)edma->ess_hw_addr + reg_addr));
  29. +}
  30. +
  31. +static int ess_reset(struct edma_common_info *edma)
  32. +{
  33. + struct device_node *switch_node = NULL;
  34. + struct reset_control *ess_rst;
  35. + u32 regval;
  36. +
  37. + switch_node = of_find_node_by_name(NULL, "ess-switch");
  38. + if (!switch_node) {
  39. + pr_err("switch-node not found\n");
  40. + return -EINVAL;
  41. + }
  42. +
  43. + ess_rst = of_reset_control_get(switch_node, "ess_rst");
  44. + of_node_put(switch_node);
  45. +
  46. + if (IS_ERR(ess_rst)) {
  47. + pr_err("failed to find ess_rst!\n");
  48. + return -ENOENT;
  49. + }
  50. +
  51. + reset_control_assert(ess_rst);
  52. + msleep(10);
  53. + reset_control_deassert(ess_rst);
  54. + msleep(100);
  55. + reset_control_put(ess_rst);
  56. +
  57. + /* Enable only port 5 <--> port 0
  58. + * bits 0:6 bitmap of ports it can fwd to */
  59. +#define SET_PORT_BMP(r,v) \
  60. + ess_read_reg(edma, r, &regval); \
  61. + ess_write_reg(edma, r, ((regval & ~0x3F) | v));
  62. +
  63. + SET_PORT_BMP(ESS_PORT0_LOOKUP_CTRL,0x20);
  64. + SET_PORT_BMP(ESS_PORT1_LOOKUP_CTRL,0x00);
  65. + SET_PORT_BMP(ESS_PORT2_LOOKUP_CTRL,0x00);
  66. + SET_PORT_BMP(ESS_PORT3_LOOKUP_CTRL,0x00);
  67. + SET_PORT_BMP(ESS_PORT4_LOOKUP_CTRL,0x00);
  68. + SET_PORT_BMP(ESS_PORT5_LOOKUP_CTRL,0x01);
  69. + ess_write_reg(edma, ESS_RGMII_CTRL, 0x400);
  70. + ess_write_reg(edma, ESS_PORT0_STATUS, ESS_PORT_1G_FDX);
  71. + ess_write_reg(edma, ESS_PORT5_STATUS, ESS_PORT_1G_FDX);
  72. + ess_write_reg(edma, ESS_PORT0_HEADER_CTRL, 0);
  73. +#undef SET_PORT_BMP
  74. +
  75. + /* forward multicast and broadcast frames to CPU */
  76. + ess_write_reg(edma, ESS_FWD_CTRL1,
  77. + (ESS_PORTS_ALL << ESS_FWD_CTRL1_UC_FLOOD_S) |
  78. + (ESS_PORTS_ALL << ESS_FWD_CTRL1_MC_FLOOD_S) |
  79. + (ESS_PORTS_ALL << ESS_FWD_CTRL1_BC_FLOOD_S));
  80. +
  81. + return 0;
  82. +}
  83. +
  84. +void ess_set_port_status_speed(struct edma_common_info *edma,
  85. + struct phy_device *phydev, uint8_t port_id)
  86. +{
  87. + uint16_t reg_off = ESS_PORT0_STATUS + (4 * port_id);
  88. + uint32_t reg_val = 0;
  89. +
  90. + ess_read_reg(edma, reg_off, &reg_val);
  91. +
  92. + /* reset the speed bits [0:1] */
  93. + reg_val &= ~ESS_PORT_STATUS_SPEED_INV;
  94. +
  95. + /* set the new speed */
  96. + switch(phydev->speed) {
  97. + case SPEED_1000: reg_val |= ESS_PORT_STATUS_SPEED_1000; break;
  98. + case SPEED_100: reg_val |= ESS_PORT_STATUS_SPEED_100; break;
  99. + case SPEED_10: reg_val |= ESS_PORT_STATUS_SPEED_10; break;
  100. + default: reg_val |= ESS_PORT_STATUS_SPEED_INV; break;
  101. + }
  102. +
  103. + /* check full/half duplex */
  104. + if (phydev->duplex) {
  105. + reg_val |= ESS_PORT_STATUS_DUPLEX_MODE;
  106. + } else {
  107. + reg_val &= ~ESS_PORT_STATUS_DUPLEX_MODE;
  108. + }
  109. +
  110. + ess_write_reg(edma, reg_off, reg_val);
  111. +}
  112. +
  113. +/*
  114. + * edma_change_tx_coalesce()
  115. * change tx interrupt moderation timer
  116. */
  117. void edma_change_tx_coalesce(int usecs)
  118. @@ -551,6 +652,31 @@ static struct ctl_table edma_table[] = {
  119. {}
  120. };
  121. +static int ess_parse(struct edma_common_info *edma)
  122. +{
  123. + struct device_node *switch_node;
  124. + int ret = -EINVAL;
  125. +
  126. + switch_node = of_find_node_by_name(NULL, "ess-switch");
  127. + if (!switch_node) {
  128. + pr_err("cannot find ess-switch node\n");
  129. + goto out;
  130. + }
  131. +
  132. + edma->ess_hw_addr = of_io_request_and_map(switch_node,
  133. + 0, KBUILD_MODNAME);
  134. + if (!edma->ess_hw_addr) {
  135. + pr_err("%s ioremap fail.", __func__);
  136. + goto out;
  137. + }
  138. +
  139. + edma->ess_clk = of_clk_get_by_name(switch_node, "ess_clk");
  140. + ret = clk_prepare_enable(edma->ess_clk);
  141. +out:
  142. + of_node_put(switch_node);
  143. + return ret;
  144. +}
  145. +
  146. /* edma_axi_netdev_ops
  147. * Describe the operations supported by registered netdevices
  148. *
  149. @@ -786,6 +912,17 @@ static int edma_axi_probe(struct platfor
  150. miibus = mdio_data->mii_bus;
  151. }
  152. + if (of_property_read_bool(np, "qcom,single-phy") &&
  153. + edma_cinfo->num_gmac == 1) {
  154. + err = ess_parse(edma_cinfo);
  155. + if (!err)
  156. + err = ess_reset(edma_cinfo);
  157. + if (err)
  158. + goto err_single_phy_init;
  159. + else
  160. + edma_cinfo->is_single_phy = true;
  161. + }
  162. +
  163. for_each_available_child_of_node(np, pnp) {
  164. const char *mac_addr;
  165. @@ -1074,11 +1211,15 @@ static int edma_axi_probe(struct platfor
  166. for (i = 0; i < edma_cinfo->num_gmac; i++) {
  167. if (adapter[i]->poll_required) {
  168. + int phy_mode = of_get_phy_mode(np);
  169. +
  170. + if (phy_mode < 0)
  171. + phy_mode = PHY_INTERFACE_MODE_SGMII;
  172. adapter[i]->phydev =
  173. phy_connect(edma_netdev[i],
  174. (const char *)adapter[i]->phy_id,
  175. &edma_adjust_link,
  176. - PHY_INTERFACE_MODE_SGMII);
  177. + phy_mode);
  178. if (IS_ERR(adapter[i]->phydev)) {
  179. dev_dbg(&pdev->dev, "PHY attach FAIL");
  180. err = -EIO;
  181. @@ -1125,6 +1266,9 @@ err_rmap_alloc_fail:
  182. for (i = 0; i < edma_cinfo->num_gmac; i++)
  183. unregister_netdev(edma_netdev[i]);
  184. err_register:
  185. +err_single_phy_init:
  186. + iounmap(edma_cinfo->ess_hw_addr);
  187. + clk_disable_unprepare(edma_cinfo->ess_clk);
  188. err_mdiobus_init_fail:
  189. edma_free_rx_rings(edma_cinfo);
  190. err_rx_rinit:
  191. @@ -1185,6 +1329,8 @@ static int edma_axi_remove(struct platfo
  192. del_timer_sync(&edma_stats_timer);
  193. edma_free_irqs(adapter);
  194. unregister_net_sysctl_table(edma_cinfo->edma_ctl_table_hdr);
  195. + iounmap(edma_cinfo->ess_hw_addr);
  196. + clk_disable_unprepare(edma_cinfo->ess_clk);
  197. edma_free_tx_resources(edma_cinfo);
  198. edma_free_rx_resources(edma_cinfo);
  199. edma_free_tx_rings(edma_cinfo);
  200. --- a/drivers/net/ethernet/qualcomm/essedma/edma.c
  201. +++ b/drivers/net/ethernet/qualcomm/essedma/edma.c
  202. @@ -161,8 +161,10 @@ static void edma_configure_rx(struct edm
  203. /* Set Rx FIFO threshold to start to DMA data to host */
  204. rxq_ctrl_data = EDMA_FIFO_THRESH_128_BYTE;
  205. - /* Set RX remove vlan bit */
  206. - rxq_ctrl_data |= EDMA_RXQ_CTRL_RMV_VLAN;
  207. + if (!edma_cinfo->is_single_phy) {
  208. + /* Set RX remove vlan bit */
  209. + rxq_ctrl_data |= EDMA_RXQ_CTRL_RMV_VLAN;
  210. + }
  211. edma_write_reg(EDMA_REG_RXQ_CTRL, rxq_ctrl_data);
  212. }
  213. @@ -1295,6 +1297,10 @@ void edma_adjust_link(struct net_device
  214. if (status == __EDMA_LINKUP && adapter->link_state == __EDMA_LINKDOWN) {
  215. dev_info(&adapter->pdev->dev, "%s: GMAC Link is up with phy_speed=%d\n", netdev->name, phydev->speed);
  216. adapter->link_state = __EDMA_LINKUP;
  217. + if (adapter->edma_cinfo->is_single_phy) {
  218. + ess_set_port_status_speed(adapter->edma_cinfo, phydev,
  219. + ffs(adapter->dp_bitmap) - 1);
  220. + }
  221. netif_carrier_on(netdev);
  222. if (netif_running(netdev))
  223. netif_tx_wake_all_queues(netdev);
  224. @@ -1388,10 +1394,12 @@ netdev_tx_t edma_xmit(struct sk_buff *sk
  225. }
  226. /* Check and mark VLAN tag offload */
  227. - if (skb_vlan_tag_present(skb))
  228. - flags_transmit |= EDMA_VLAN_TX_TAG_INSERT_FLAG;
  229. - else if (adapter->default_vlan_tag)
  230. - flags_transmit |= EDMA_VLAN_TX_TAG_INSERT_DEFAULT_FLAG;
  231. + if (!adapter->edma_cinfo->is_single_phy) {
  232. + if (unlikely(skb_vlan_tag_present(skb)))
  233. + flags_transmit |= EDMA_VLAN_TX_TAG_INSERT_FLAG;
  234. + else if (adapter->default_vlan_tag)
  235. + flags_transmit |= EDMA_VLAN_TX_TAG_INSERT_DEFAULT_FLAG;
  236. + }
  237. /* Check and mark checksum offload */
  238. if (likely(skb->ip_summed == CHECKSUM_PARTIAL))
  239. --- a/drivers/net/ethernet/qualcomm/essedma/edma.h
  240. +++ b/drivers/net/ethernet/qualcomm/essedma/edma.h
  241. @@ -31,6 +31,7 @@
  242. #include <linux/platform_device.h>
  243. #include <linux/of.h>
  244. #include <linux/of_device.h>
  245. +#include <linux/clk.h>
  246. #include <linux/kernel.h>
  247. #include <linux/device.h>
  248. #include <linux/sysctl.h>
  249. @@ -331,6 +332,10 @@ struct edma_common_info {
  250. struct edma_hw hw; /* edma hw specific structure */
  251. struct edma_per_cpu_queues_info edma_percpu_info[CONFIG_NR_CPUS]; /* per cpu information */
  252. spinlock_t stats_lock; /* protect edma stats area for updation */
  253. +
  254. + bool is_single_phy;
  255. + void __iomem *ess_hw_addr;
  256. + struct clk *ess_clk;
  257. };
  258. /* transimit packet descriptor (tpd) ring */
  259. @@ -443,4 +448,6 @@ void edma_change_tx_coalesce(int usecs);
  260. void edma_change_rx_coalesce(int usecs);
  261. void edma_get_tx_rx_coalesce(u32 *reg_val);
  262. void edma_clear_irq_status(void);
  263. +void ess_set_port_status_speed(struct edma_common_info *edma_cinfo,
  264. + struct phy_device *phydev, uint8_t port_id);
  265. #endif /* _EDMA_H_ */
  266. --- a/drivers/net/ethernet/qualcomm/essedma/ess_edma.h
  267. +++ b/drivers/net/ethernet/qualcomm/essedma/ess_edma.h
  268. @@ -329,4 +329,61 @@ struct edma_hw;
  269. #define EDMA_RRD_PRIORITY_MASK 0x7
  270. #define EDMA_RRD_PORT_TYPE_SHIFT 7
  271. #define EDMA_RRD_PORT_TYPE_MASK 0x1F
  272. +
  273. +#define ESS_RGMII_CTRL 0x0004
  274. +
  275. +/* Port status registers */
  276. +#define ESS_PORT0_STATUS 0x007C
  277. +#define ESS_PORT1_STATUS 0x0080
  278. +#define ESS_PORT2_STATUS 0x0084
  279. +#define ESS_PORT3_STATUS 0x0088
  280. +#define ESS_PORT4_STATUS 0x008C
  281. +#define ESS_PORT5_STATUS 0x0090
  282. +
  283. +#define ESS_PORT_STATUS_HDX_FLOW_CTL 0x80
  284. +#define ESS_PORT_STATUS_DUPLEX_MODE 0x40
  285. +#define ESS_PORT_STATUS_RX_FLOW_EN 0x20
  286. +#define ESS_PORT_STATUS_TX_FLOW_EN 0x10
  287. +#define ESS_PORT_STATUS_RX_MAC_EN 0x08
  288. +#define ESS_PORT_STATUS_TX_MAC_EN 0x04
  289. +#define ESS_PORT_STATUS_SPEED_INV 0x03
  290. +#define ESS_PORT_STATUS_SPEED_1000 0x02
  291. +#define ESS_PORT_STATUS_SPEED_100 0x01
  292. +#define ESS_PORT_STATUS_SPEED_10 0x00
  293. +
  294. +#define ESS_PORT_1G_FDX (ESS_PORT_STATUS_DUPLEX_MODE | ESS_PORT_STATUS_RX_FLOW_EN | \
  295. + ESS_PORT_STATUS_TX_FLOW_EN | ESS_PORT_STATUS_RX_MAC_EN | \
  296. + ESS_PORT_STATUS_TX_MAC_EN | ESS_PORT_STATUS_SPEED_1000)
  297. +
  298. +#define PHY_STATUS_REG 0x11
  299. +#define PHY_STATUS_SPEED 0xC000
  300. +#define PHY_STATUS_SPEED_SHIFT 14
  301. +#define PHY_STATUS_DUPLEX 0x2000
  302. +#define PHY_STATUS_DUPLEX_SHIFT 13
  303. +#define PHY_STATUS_SPEED_DUPLEX_RESOLVED 0x0800
  304. +#define PHY_STATUS_CARRIER 0x0400
  305. +#define PHY_STATUS_CARRIER_SHIFT 10
  306. +
  307. +/* Port lookup control registers */
  308. +#define ESS_PORT0_LOOKUP_CTRL 0x0660
  309. +#define ESS_PORT1_LOOKUP_CTRL 0x066C
  310. +#define ESS_PORT2_LOOKUP_CTRL 0x0678
  311. +#define ESS_PORT3_LOOKUP_CTRL 0x0684
  312. +#define ESS_PORT4_LOOKUP_CTRL 0x0690
  313. +#define ESS_PORT5_LOOKUP_CTRL 0x069C
  314. +
  315. +#define ESS_PORT0_HEADER_CTRL 0x009C
  316. +
  317. +#define ESS_PORTS_ALL 0x3f
  318. +
  319. +#define ESS_FWD_CTRL1 0x0624
  320. +#define ESS_FWD_CTRL1_UC_FLOOD BITS(0, 7)
  321. +#define ESS_FWD_CTRL1_UC_FLOOD_S 0
  322. +#define ESS_FWD_CTRL1_MC_FLOOD BITS(8, 7)
  323. +#define ESS_FWD_CTRL1_MC_FLOOD_S 8
  324. +#define ESS_FWD_CTRL1_BC_FLOOD BITS(16, 7)
  325. +#define ESS_FWD_CTRL1_BC_FLOOD_S 16
  326. +#define ESS_FWD_CTRL1_IGMP BITS(24, 7)
  327. +#define ESS_FWD_CTRL1_IGMP_S 24
  328. +
  329. #endif /* _ESS_EDMA_H_ */