aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/ethernet/qualcomm/emac/emac-mac.c8
-rw-r--r--drivers/net/ethernet/qualcomm/emac/emac-sgmii.c126
-rw-r--r--drivers/net/ethernet/qualcomm/emac/emac-sgmii.h16
-rw-r--r--drivers/net/ethernet/qualcomm/emac/emac.c10
4 files changed, 153 insertions, 7 deletions
diff --git a/drivers/net/ethernet/qualcomm/emac/emac-mac.c b/drivers/net/ethernet/qualcomm/emac/emac-mac.c
index 33d7ff1f40e0..b991219862b1 100644
--- a/drivers/net/ethernet/qualcomm/emac/emac-mac.c
+++ b/drivers/net/ethernet/qualcomm/emac/emac-mac.c
@@ -951,12 +951,16 @@ static void emac_mac_rx_descs_refill(struct emac_adapter *adpt,
951static void emac_adjust_link(struct net_device *netdev) 951static void emac_adjust_link(struct net_device *netdev)
952{ 952{
953 struct emac_adapter *adpt = netdev_priv(netdev); 953 struct emac_adapter *adpt = netdev_priv(netdev);
954 struct emac_sgmii *sgmii = &adpt->phy;
954 struct phy_device *phydev = netdev->phydev; 955 struct phy_device *phydev = netdev->phydev;
955 956
956 if (phydev->link) 957 if (phydev->link) {
957 emac_mac_start(adpt); 958 emac_mac_start(adpt);
958 else 959 sgmii->link_up(adpt);
960 } else {
961 sgmii->link_down(adpt);
959 emac_mac_stop(adpt); 962 emac_mac_stop(adpt);
963 }
960 964
961 phy_print_status(phydev); 965 phy_print_status(phydev);
962} 966}
diff --git a/drivers/net/ethernet/qualcomm/emac/emac-sgmii.c b/drivers/net/ethernet/qualcomm/emac/emac-sgmii.c
index b5269c4dd4ee..040b28977ee7 100644
--- a/drivers/net/ethernet/qualcomm/emac/emac-sgmii.c
+++ b/drivers/net/ethernet/qualcomm/emac/emac-sgmii.c
@@ -25,7 +25,9 @@
25#define EMAC_SGMII_PHY_SPEED_CFG1 0x0074 25#define EMAC_SGMII_PHY_SPEED_CFG1 0x0074
26#define EMAC_SGMII_PHY_IRQ_CMD 0x00ac 26#define EMAC_SGMII_PHY_IRQ_CMD 0x00ac
27#define EMAC_SGMII_PHY_INTERRUPT_CLEAR 0x00b0 27#define EMAC_SGMII_PHY_INTERRUPT_CLEAR 0x00b0
28#define EMAC_SGMII_PHY_INTERRUPT_MASK 0x00b4
28#define EMAC_SGMII_PHY_INTERRUPT_STATUS 0x00b8 29#define EMAC_SGMII_PHY_INTERRUPT_STATUS 0x00b8
30#define EMAC_SGMII_PHY_RX_CHK_STATUS 0x00d4
29 31
30#define FORCE_AN_TX_CFG BIT(5) 32#define FORCE_AN_TX_CFG BIT(5)
31#define FORCE_AN_RX_CFG BIT(4) 33#define FORCE_AN_RX_CFG BIT(4)
@@ -36,6 +38,8 @@
36#define SPDMODE_100 BIT(0) 38#define SPDMODE_100 BIT(0)
37#define SPDMODE_10 0 39#define SPDMODE_10 0
38 40
41#define CDR_ALIGN_DET BIT(6)
42
39#define IRQ_GLOBAL_CLEAR BIT(0) 43#define IRQ_GLOBAL_CLEAR BIT(0)
40 44
41#define DECODE_CODE_ERR BIT(7) 45#define DECODE_CODE_ERR BIT(7)
@@ -44,6 +48,7 @@
44#define SGMII_PHY_IRQ_CLR_WAIT_TIME 10 48#define SGMII_PHY_IRQ_CLR_WAIT_TIME 10
45 49
46#define SGMII_PHY_INTERRUPT_ERR (DECODE_CODE_ERR | DECODE_DISP_ERR) 50#define SGMII_PHY_INTERRUPT_ERR (DECODE_CODE_ERR | DECODE_DISP_ERR)
51#define SGMII_ISR_MASK (SGMII_PHY_INTERRUPT_ERR)
47 52
48#define SERDES_START_WAIT_TIMES 100 53#define SERDES_START_WAIT_TIMES 100
49 54
@@ -96,6 +101,51 @@ static int emac_sgmii_irq_clear(struct emac_adapter *adpt, u32 irq_bits)
96 return 0; 101 return 0;
97} 102}
98 103
104/* The number of decode errors that triggers a reset */
105#define DECODE_ERROR_LIMIT 2
106
107static irqreturn_t emac_sgmii_interrupt(int irq, void *data)
108{
109 struct emac_adapter *adpt = data;
110 struct emac_sgmii *phy = &adpt->phy;
111 u32 status;
112
113 status = readl(phy->base + EMAC_SGMII_PHY_INTERRUPT_STATUS);
114 status &= SGMII_ISR_MASK;
115 if (!status)
116 return IRQ_HANDLED;
117
118 /* If we get a decoding error and CDR is not locked, then try
119 * resetting the internal PHY. The internal PHY uses an embedded
120 * clock with Clock and Data Recovery (CDR) to recover the
121 * clock and data.
122 */
123 if (status & SGMII_PHY_INTERRUPT_ERR) {
124 int count;
125
126 /* The SGMII is capable of recovering from some decode
127 * errors automatically. However, if we get multiple
128 * decode errors in a row, then assume that something
129 * is wrong and reset the interface.
130 */
131 count = atomic_inc_return(&phy->decode_error_count);
132 if (count == DECODE_ERROR_LIMIT) {
133 schedule_work(&adpt->work_thread);
134 atomic_set(&phy->decode_error_count, 0);
135 }
136 } else {
137 /* We only care about consecutive decode errors. */
138 atomic_set(&phy->decode_error_count, 0);
139 }
140
141 if (emac_sgmii_irq_clear(adpt, status)) {
142 netdev_warn(adpt->netdev, "failed to clear SGMII interrupt\n");
143 schedule_work(&adpt->work_thread);
144 }
145
146 return IRQ_HANDLED;
147}
148
99static void emac_sgmii_reset_prepare(struct emac_adapter *adpt) 149static void emac_sgmii_reset_prepare(struct emac_adapter *adpt)
100{ 150{
101 struct emac_sgmii *phy = &adpt->phy; 151 struct emac_sgmii *phy = &adpt->phy;
@@ -129,6 +179,68 @@ void emac_sgmii_reset(struct emac_adapter *adpt)
129 ret); 179 ret);
130} 180}
131 181
182static int emac_sgmii_open(struct emac_adapter *adpt)
183{
184 struct emac_sgmii *sgmii = &adpt->phy;
185 int ret;
186
187 if (sgmii->irq) {
188 /* Make sure interrupts are cleared and disabled first */
189 ret = emac_sgmii_irq_clear(adpt, 0xff);
190 if (ret)
191 return ret;
192 writel(0, sgmii->base + EMAC_SGMII_PHY_INTERRUPT_MASK);
193
194 ret = request_irq(sgmii->irq, emac_sgmii_interrupt, 0,
195 "emac-sgmii", adpt);
196 if (ret) {
197 netdev_err(adpt->netdev,
198 "could not register handler for internal PHY\n");
199 return ret;
200 }
201 }
202
203 return 0;
204}
205
206static int emac_sgmii_close(struct emac_adapter *adpt)
207{
208 struct emac_sgmii *sgmii = &adpt->phy;
209
210 /* Make sure interrupts are disabled */
211 writel(0, sgmii->base + EMAC_SGMII_PHY_INTERRUPT_MASK);
212 free_irq(sgmii->irq, adpt);
213
214 return 0;
215}
216
217/* The error interrupts are only valid after the link is up */
218static int emac_sgmii_link_up(struct emac_adapter *adpt)
219{
220 struct emac_sgmii *sgmii = &adpt->phy;
221 int ret;
222
223 /* Clear and enable interrupts */
224 ret = emac_sgmii_irq_clear(adpt, 0xff);
225 if (ret)
226 return ret;
227
228 writel(SGMII_ISR_MASK, sgmii->base + EMAC_SGMII_PHY_INTERRUPT_MASK);
229
230 return 0;
231}
232
233static int emac_sgmii_link_down(struct emac_adapter *adpt)
234{
235 struct emac_sgmii *sgmii = &adpt->phy;
236
237 /* Disable interrupts */
238 writel(0, sgmii->base + EMAC_SGMII_PHY_INTERRUPT_MASK);
239 synchronize_irq(sgmii->irq);
240
241 return 0;
242}
243
132static int emac_sgmii_acpi_match(struct device *dev, void *data) 244static int emac_sgmii_acpi_match(struct device *dev, void *data)
133{ 245{
134#ifdef CONFIG_ACPI 246#ifdef CONFIG_ACPI
@@ -139,7 +251,7 @@ static int emac_sgmii_acpi_match(struct device *dev, void *data)
139 {} 251 {}
140 }; 252 };
141 const struct acpi_device_id *id = acpi_match_device(match_table, dev); 253 const struct acpi_device_id *id = acpi_match_device(match_table, dev);
142 emac_sgmii_initialize *initialize = data; 254 emac_sgmii_function *initialize = data;
143 255
144 if (id) { 256 if (id) {
145 acpi_handle handle = ACPI_HANDLE(dev); 257 acpi_handle handle = ACPI_HANDLE(dev);
@@ -226,9 +338,14 @@ int emac_sgmii_config(struct platform_device *pdev, struct emac_adapter *adpt)
226 goto error_put_device; 338 goto error_put_device;
227 } 339 }
228 340
229 phy->initialize = (emac_sgmii_initialize)match->data; 341 phy->initialize = (emac_sgmii_function)match->data;
230 } 342 }
231 343
344 phy->open = emac_sgmii_open;
345 phy->close = emac_sgmii_close;
346 phy->link_up = emac_sgmii_link_up;
347 phy->link_down = emac_sgmii_link_down;
348
232 /* Base address is the first address */ 349 /* Base address is the first address */
233 res = platform_get_resource(sgmii_pdev, IORESOURCE_MEM, 0); 350 res = platform_get_resource(sgmii_pdev, IORESOURCE_MEM, 0);
234 if (!res) { 351 if (!res) {
@@ -256,9 +373,12 @@ int emac_sgmii_config(struct platform_device *pdev, struct emac_adapter *adpt)
256 if (ret) 373 if (ret)
257 goto error; 374 goto error;
258 375
259 emac_sgmii_irq_clear(adpt, SGMII_PHY_INTERRUPT_ERR);
260 emac_sgmii_link_init(adpt); 376 emac_sgmii_link_init(adpt);
261 377
378 ret = platform_get_irq(sgmii_pdev, 0);
379 if (ret > 0)
380 phy->irq = ret;
381
262 /* We've remapped the addresses, so we don't need the device any 382 /* We've remapped the addresses, so we don't need the device any
263 * more. of_find_device_by_node() says we should release it. 383 * more. of_find_device_by_node() says we should release it.
264 */ 384 */
diff --git a/drivers/net/ethernet/qualcomm/emac/emac-sgmii.h b/drivers/net/ethernet/qualcomm/emac/emac-sgmii.h
index 4a8f6b174f4b..e7c0c3b2baa4 100644
--- a/drivers/net/ethernet/qualcomm/emac/emac-sgmii.h
+++ b/drivers/net/ethernet/qualcomm/emac/emac-sgmii.h
@@ -16,17 +16,29 @@
16struct emac_adapter; 16struct emac_adapter;
17struct platform_device; 17struct platform_device;
18 18
19typedef int (*emac_sgmii_initialize)(struct emac_adapter *adpt); 19typedef int (*emac_sgmii_function)(struct emac_adapter *adpt);
20 20
21/** emac_sgmii - internal emac phy 21/** emac_sgmii - internal emac phy
22 * @base base address 22 * @base base address
23 * @digital per-lane digital block 23 * @digital per-lane digital block
24 * @irq the interrupt number
25 * @decode_error_count reference count of consecutive decode errors
24 * @initialize initialization function 26 * @initialize initialization function
27 * @open called when the driver is opened
28 * @close called when the driver is closed
29 * @link_up called when the link comes up
30 * @link_down called when the link comes down
25 */ 31 */
26struct emac_sgmii { 32struct emac_sgmii {
27 void __iomem *base; 33 void __iomem *base;
28 void __iomem *digital; 34 void __iomem *digital;
29 emac_sgmii_initialize initialize; 35 unsigned int irq;
36 atomic_t decode_error_count;
37 emac_sgmii_function initialize;
38 emac_sgmii_function open;
39 emac_sgmii_function close;
40 emac_sgmii_function link_up;
41 emac_sgmii_function link_down;
30}; 42};
31 43
32int emac_sgmii_config(struct platform_device *pdev, struct emac_adapter *adpt); 44int emac_sgmii_config(struct platform_device *pdev, struct emac_adapter *adpt);
diff --git a/drivers/net/ethernet/qualcomm/emac/emac.c b/drivers/net/ethernet/qualcomm/emac/emac.c
index 75305ad436d5..f519351ef3a2 100644
--- a/drivers/net/ethernet/qualcomm/emac/emac.c
+++ b/drivers/net/ethernet/qualcomm/emac/emac.c
@@ -280,6 +280,14 @@ static int emac_open(struct net_device *netdev)
280 return ret; 280 return ret;
281 } 281 }
282 282
283 ret = adpt->phy.open(adpt);
284 if (ret) {
285 emac_mac_down(adpt);
286 emac_mac_rx_tx_rings_free_all(adpt);
287 free_irq(irq->irq, irq);
288 return ret;
289 }
290
283 return 0; 291 return 0;
284} 292}
285 293
@@ -290,6 +298,7 @@ static int emac_close(struct net_device *netdev)
290 298
291 mutex_lock(&adpt->reset_lock); 299 mutex_lock(&adpt->reset_lock);
292 300
301 adpt->phy.close(adpt);
293 emac_mac_down(adpt); 302 emac_mac_down(adpt);
294 emac_mac_rx_tx_rings_free_all(adpt); 303 emac_mac_rx_tx_rings_free_all(adpt);
295 304
@@ -645,6 +654,7 @@ static int emac_probe(struct platform_device *pdev)
645 adpt->msg_enable = EMAC_MSG_DEFAULT; 654 adpt->msg_enable = EMAC_MSG_DEFAULT;
646 655
647 phy = &adpt->phy; 656 phy = &adpt->phy;
657 atomic_set(&phy->decode_error_count, 0);
648 658
649 mutex_init(&adpt->reset_lock); 659 mutex_init(&adpt->reset_lock);
650 spin_lock_init(&adpt->stats.lock); 660 spin_lock_init(&adpt->stats.lock);