Lines Matching +full:switch +full:- +full:x +full:- +full:sgmii

1 // SPDX-License-Identifier: GPL-2.0-only
2 /* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved.
5 /* Qualcomm Technologies, Inc. EMAC SGMII Controller driver.
15 #include "emac-mac.h"
16 #include "emac-sgmii.h"
52 if (!(adpt->phy.sgmii_ops && adpt->phy.sgmii_ops->init)) in emac_sgmii_init()
55 return adpt->phy.sgmii_ops->init(adpt); in emac_sgmii_init()
60 if (!(adpt->phy.sgmii_ops && adpt->phy.sgmii_ops->open)) in emac_sgmii_open()
63 return adpt->phy.sgmii_ops->open(adpt); in emac_sgmii_open()
68 if (!(adpt->phy.sgmii_ops && adpt->phy.sgmii_ops->close)) in emac_sgmii_close()
71 adpt->phy.sgmii_ops->close(adpt); in emac_sgmii_close()
76 if (!(adpt->phy.sgmii_ops && adpt->phy.sgmii_ops->link_change)) in emac_sgmii_link_change()
79 return adpt->phy.sgmii_ops->link_change(adpt, link_state); in emac_sgmii_link_change()
84 if (!(adpt->phy.sgmii_ops && adpt->phy.sgmii_ops->reset)) in emac_sgmii_reset()
87 adpt->phy.sgmii_ops->reset(adpt); in emac_sgmii_reset()
90 /* Initialize the SGMII link between the internal and external PHYs. */
93 struct emac_sgmii *phy = &adpt->phy; in emac_sgmii_link_init()
99 val = readl(phy->base + EMAC_SGMII_PHY_AUTONEG_CFG2); in emac_sgmii_link_init()
102 writel(val, phy->base + EMAC_SGMII_PHY_AUTONEG_CFG2); in emac_sgmii_link_init()
107 struct emac_sgmii *phy = &adpt->phy; in emac_sgmii_irq_clear()
110 writel_relaxed(irq_bits, phy->base + EMAC_SGMII_PHY_INTERRUPT_CLEAR); in emac_sgmii_irq_clear()
111 writel_relaxed(IRQ_GLOBAL_CLEAR, phy->base + EMAC_SGMII_PHY_IRQ_CMD); in emac_sgmii_irq_clear()
119 if (readl_poll_timeout_atomic(phy->base + in emac_sgmii_irq_clear()
123 net_err_ratelimited("%s: failed to clear SGMII irq: status:0x%x bits:0x%x\n", in emac_sgmii_irq_clear()
124 adpt->netdev->name, status, irq_bits); in emac_sgmii_irq_clear()
125 return -EIO; in emac_sgmii_irq_clear()
129 writel_relaxed(0, phy->base + EMAC_SGMII_PHY_IRQ_CMD); in emac_sgmii_irq_clear()
130 writel_relaxed(0, phy->base + EMAC_SGMII_PHY_INTERRUPT_CLEAR); in emac_sgmii_irq_clear()
144 struct emac_sgmii *phy = &adpt->phy; in emac_sgmii_interrupt()
147 status = readl(phy->base + EMAC_SGMII_PHY_INTERRUPT_STATUS); in emac_sgmii_interrupt()
160 /* The SGMII is capable of recovering from some decode in emac_sgmii_interrupt()
165 count = atomic_inc_return(&phy->decode_error_count); in emac_sgmii_interrupt()
167 schedule_work(&adpt->work_thread); in emac_sgmii_interrupt()
168 atomic_set(&phy->decode_error_count, 0); in emac_sgmii_interrupt()
172 atomic_set(&phy->decode_error_count, 0); in emac_sgmii_interrupt()
176 schedule_work(&adpt->work_thread); in emac_sgmii_interrupt()
183 struct emac_sgmii *phy = &adpt->phy; in emac_sgmii_reset_prepare()
187 val = readl(phy->base + EMAC_EMAC_WRAPPER_CSR2); in emac_sgmii_reset_prepare()
188 writel(((val & ~PHY_RESET) | PHY_RESET), phy->base + in emac_sgmii_reset_prepare()
190 /* Ensure phy-reset command is written to HW before the release cmd */ in emac_sgmii_reset_prepare()
192 val = readl(phy->base + EMAC_EMAC_WRAPPER_CSR2); in emac_sgmii_reset_prepare()
193 writel((val & ~PHY_RESET), phy->base + EMAC_EMAC_WRAPPER_CSR2); in emac_sgmii_reset_prepare()
194 /* Ensure phy-reset release command is written to HW before initializing in emac_sgmii_reset_prepare()
195 * SGMII in emac_sgmii_reset_prepare()
209 netdev_err(adpt->netdev, in emac_sgmii_common_reset()
216 struct emac_sgmii *sgmii = &adpt->phy; in emac_sgmii_common_open() local
219 if (sgmii->irq) { in emac_sgmii_common_open()
224 writel(0, sgmii->base + EMAC_SGMII_PHY_INTERRUPT_MASK); in emac_sgmii_common_open()
226 ret = request_irq(sgmii->irq, emac_sgmii_interrupt, 0, in emac_sgmii_common_open()
227 "emac-sgmii", adpt); in emac_sgmii_common_open()
229 netdev_err(adpt->netdev, in emac_sgmii_common_open()
240 struct emac_sgmii *sgmii = &adpt->phy; in emac_sgmii_common_close() local
243 writel(0, sgmii->base + EMAC_SGMII_PHY_INTERRUPT_MASK); in emac_sgmii_common_close()
244 free_irq(sgmii->irq, adpt); in emac_sgmii_common_close()
250 struct emac_sgmii *sgmii = &adpt->phy; in emac_sgmii_common_link_change() local
260 sgmii->base + EMAC_SGMII_PHY_INTERRUPT_MASK); in emac_sgmii_common_link_change()
263 writel(0, sgmii->base + EMAC_SGMII_PHY_INTERRUPT_MASK); in emac_sgmii_common_link_change()
264 synchronize_irq(sgmii->irq); in emac_sgmii_common_link_change()
325 switch (hrv) { in emac_sgmii_acpi_match()
341 .compatible = "qcom,fsm9900-emac-sgmii",
345 .compatible = "qcom,qdf2432-emac-sgmii",
354 struct emac_sgmii *phy = &adpt->phy; in emac_sgmii_config()
358 if (has_acpi_companion(&pdev->dev)) { in emac_sgmii_config()
361 dev = device_find_child(&pdev->dev, &phy->sgmii_ops, in emac_sgmii_config()
365 dev_warn(&pdev->dev, "cannot find internal phy node\n"); in emac_sgmii_config()
374 np = of_parse_phandle(pdev->dev.of_node, "internal-phy", 0); in emac_sgmii_config()
376 dev_err(&pdev->dev, "missing internal-phy property\n"); in emac_sgmii_config()
377 return -ENODEV; in emac_sgmii_config()
383 dev_err(&pdev->dev, "invalid internal-phy property\n"); in emac_sgmii_config()
384 return -ENODEV; in emac_sgmii_config()
387 match = of_match_device(emac_sgmii_dt_match, &sgmii_pdev->dev); in emac_sgmii_config()
389 dev_err(&pdev->dev, "unrecognized internal phy node\n"); in emac_sgmii_config()
390 ret = -ENODEV; in emac_sgmii_config()
394 phy->sgmii_ops = (struct sgmii_ops *)match->data; in emac_sgmii_config()
400 ret = -EINVAL; in emac_sgmii_config()
404 phy->base = ioremap(res->start, resource_size(res)); in emac_sgmii_config()
405 if (!phy->base) { in emac_sgmii_config()
406 ret = -ENOMEM; in emac_sgmii_config()
410 /* v2 SGMII has a per-lane digital digital, so parse it if it exists */ in emac_sgmii_config()
413 phy->digital = ioremap(res->start, resource_size(res)); in emac_sgmii_config()
414 if (!phy->digital) { in emac_sgmii_config()
415 ret = -ENOMEM; in emac_sgmii_config()
428 phy->irq = ret; in emac_sgmii_config()
433 put_device(&sgmii_pdev->dev); in emac_sgmii_config()
438 if (phy->digital) in emac_sgmii_config()
439 iounmap(phy->digital); in emac_sgmii_config()
441 iounmap(phy->base); in emac_sgmii_config()
443 put_device(&sgmii_pdev->dev); in emac_sgmii_config()