linux/drivers/net/ethernet/qualcomm/emac/emac-sgmii.c
<<
>>
Prefs
   1/* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved.
   2 *
   3 * This program is free software; you can redistribute it and/or modify
   4 * it under the terms of the GNU General Public License version 2 and
   5 * only version 2 as published by the Free Software Foundation.
   6 *
   7 * This program is distributed in the hope that it will be useful,
   8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
   9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  10 * GNU General Public License for more details.
  11 */
  12
  13/* Qualcomm Technologies, Inc. EMAC SGMII Controller driver.
  14 */
  15
  16#include <linux/interrupt.h>
  17#include <linux/iopoll.h>
  18#include <linux/acpi.h>
  19#include <linux/of_device.h>
  20#include "emac.h"
  21#include "emac-mac.h"
  22#include "emac-sgmii.h"
  23
  24/* EMAC_SGMII register offsets */
  25#define EMAC_SGMII_PHY_AUTONEG_CFG2             0x0048
  26#define EMAC_SGMII_PHY_SPEED_CFG1               0x0074
  27#define EMAC_SGMII_PHY_IRQ_CMD                  0x00ac
  28#define EMAC_SGMII_PHY_INTERRUPT_CLEAR          0x00b0
  29#define EMAC_SGMII_PHY_INTERRUPT_MASK           0x00b4
  30#define EMAC_SGMII_PHY_INTERRUPT_STATUS         0x00b8
  31#define EMAC_SGMII_PHY_RX_CHK_STATUS            0x00d4
  32
  33#define FORCE_AN_TX_CFG                         BIT(5)
  34#define FORCE_AN_RX_CFG                         BIT(4)
  35#define AN_ENABLE                               BIT(0)
  36
  37#define DUPLEX_MODE                             BIT(4)
  38#define SPDMODE_1000                            BIT(1)
  39#define SPDMODE_100                             BIT(0)
  40#define SPDMODE_10                              0
  41
  42#define CDR_ALIGN_DET                           BIT(6)
  43
  44#define IRQ_GLOBAL_CLEAR                        BIT(0)
  45
  46#define DECODE_CODE_ERR                         BIT(7)
  47#define DECODE_DISP_ERR                         BIT(6)
  48
  49#define SGMII_PHY_IRQ_CLR_WAIT_TIME             10
  50
  51#define SGMII_PHY_INTERRUPT_ERR         (DECODE_CODE_ERR | DECODE_DISP_ERR)
  52#define SGMII_ISR_MASK                  (SGMII_PHY_INTERRUPT_ERR)
  53
  54#define SERDES_START_WAIT_TIMES                 100
  55
  56int emac_sgmii_init(struct emac_adapter *adpt)
  57{
  58        if (!(adpt->phy.sgmii_ops && adpt->phy.sgmii_ops->init))
  59                return 0;
  60
  61        return adpt->phy.sgmii_ops->init(adpt);
  62}
  63
  64int emac_sgmii_open(struct emac_adapter *adpt)
  65{
  66        if (!(adpt->phy.sgmii_ops && adpt->phy.sgmii_ops->open))
  67                return 0;
  68
  69        return adpt->phy.sgmii_ops->open(adpt);
  70}
  71
  72void emac_sgmii_close(struct emac_adapter *adpt)
  73{
  74        if (!(adpt->phy.sgmii_ops && adpt->phy.sgmii_ops->close))
  75                return;
  76
  77        adpt->phy.sgmii_ops->close(adpt);
  78}
  79
  80int emac_sgmii_link_change(struct emac_adapter *adpt, bool link_state)
  81{
  82        if (!(adpt->phy.sgmii_ops && adpt->phy.sgmii_ops->link_change))
  83                return 0;
  84
  85        return adpt->phy.sgmii_ops->link_change(adpt, link_state);
  86}
  87
  88void emac_sgmii_reset(struct emac_adapter *adpt)
  89{
  90        if (!(adpt->phy.sgmii_ops && adpt->phy.sgmii_ops->reset))
  91                return;
  92
  93        adpt->phy.sgmii_ops->reset(adpt);
  94}
  95
  96/* Initialize the SGMII link between the internal and external PHYs. */
  97static void emac_sgmii_link_init(struct emac_adapter *adpt)
  98{
  99        struct emac_sgmii *phy = &adpt->phy;
 100        u32 val;
 101
 102        /* Always use autonegotiation. It works no matter how the external
 103         * PHY is configured.
 104         */
 105        val = readl(phy->base + EMAC_SGMII_PHY_AUTONEG_CFG2);
 106        val &= ~(FORCE_AN_RX_CFG | FORCE_AN_TX_CFG);
 107        val |= AN_ENABLE;
 108        writel(val, phy->base + EMAC_SGMII_PHY_AUTONEG_CFG2);
 109}
 110
 111static int emac_sgmii_irq_clear(struct emac_adapter *adpt, u8 irq_bits)
 112{
 113        struct emac_sgmii *phy = &adpt->phy;
 114        u8 status;
 115
 116        writel_relaxed(irq_bits, phy->base + EMAC_SGMII_PHY_INTERRUPT_CLEAR);
 117        writel_relaxed(IRQ_GLOBAL_CLEAR, phy->base + EMAC_SGMII_PHY_IRQ_CMD);
 118        /* Ensure interrupt clear command is written to HW */
 119        wmb();
 120
 121        /* After set the IRQ_GLOBAL_CLEAR bit, the status clearing must
 122         * be confirmed before clearing the bits in other registers.
 123         * It takes a few cycles for hw to clear the interrupt status.
 124         */
 125        if (readl_poll_timeout_atomic(phy->base +
 126                                      EMAC_SGMII_PHY_INTERRUPT_STATUS,
 127                                      status, !(status & irq_bits), 1,
 128                                      SGMII_PHY_IRQ_CLR_WAIT_TIME)) {
 129                net_err_ratelimited("%s: failed to clear SGMII irq: status:0x%x bits:0x%x\n",
 130                                    adpt->netdev->name, status, irq_bits);
 131                return -EIO;
 132        }
 133
 134        /* Finalize clearing procedure */
 135        writel_relaxed(0, phy->base + EMAC_SGMII_PHY_IRQ_CMD);
 136        writel_relaxed(0, phy->base + EMAC_SGMII_PHY_INTERRUPT_CLEAR);
 137
 138        /* Ensure that clearing procedure finalization is written to HW */
 139        wmb();
 140
 141        return 0;
 142}
 143
 144/* The number of decode errors that triggers a reset */
 145#define DECODE_ERROR_LIMIT      2
 146
 147static irqreturn_t emac_sgmii_interrupt(int irq, void *data)
 148{
 149        struct emac_adapter *adpt = data;
 150        struct emac_sgmii *phy = &adpt->phy;
 151        u8 status;
 152
 153        status = readl(phy->base + EMAC_SGMII_PHY_INTERRUPT_STATUS);
 154        status &= SGMII_ISR_MASK;
 155        if (!status)
 156                return IRQ_HANDLED;
 157
 158        /* If we get a decoding error and CDR is not locked, then try
 159         * resetting the internal PHY.  The internal PHY uses an embedded
 160         * clock with Clock and Data Recovery (CDR) to recover the
 161         * clock and data.
 162         */
 163        if (status & SGMII_PHY_INTERRUPT_ERR) {
 164                int count;
 165
 166                /* The SGMII is capable of recovering from some decode
 167                 * errors automatically.  However, if we get multiple
 168                 * decode errors in a row, then assume that something
 169                 * is wrong and reset the interface.
 170                 */
 171                count = atomic_inc_return(&phy->decode_error_count);
 172                if (count == DECODE_ERROR_LIMIT) {
 173                        schedule_work(&adpt->work_thread);
 174                        atomic_set(&phy->decode_error_count, 0);
 175                }
 176        } else {
 177                /* We only care about consecutive decode errors. */
 178                atomic_set(&phy->decode_error_count, 0);
 179        }
 180
 181        if (emac_sgmii_irq_clear(adpt, status))
 182                schedule_work(&adpt->work_thread);
 183
 184        return IRQ_HANDLED;
 185}
 186
 187static void emac_sgmii_reset_prepare(struct emac_adapter *adpt)
 188{
 189        struct emac_sgmii *phy = &adpt->phy;
 190        u32 val;
 191
 192        /* Reset PHY */
 193        val = readl(phy->base + EMAC_EMAC_WRAPPER_CSR2);
 194        writel(((val & ~PHY_RESET) | PHY_RESET), phy->base +
 195               EMAC_EMAC_WRAPPER_CSR2);
 196        /* Ensure phy-reset command is written to HW before the release cmd */
 197        msleep(50);
 198        val = readl(phy->base + EMAC_EMAC_WRAPPER_CSR2);
 199        writel((val & ~PHY_RESET), phy->base + EMAC_EMAC_WRAPPER_CSR2);
 200        /* Ensure phy-reset release command is written to HW before initializing
 201         * SGMII
 202         */
 203        msleep(50);
 204}
 205
 206static void emac_sgmii_common_reset(struct emac_adapter *adpt)
 207{
 208        int ret;
 209
 210        emac_sgmii_reset_prepare(adpt);
 211        emac_sgmii_link_init(adpt);
 212
 213        ret = emac_sgmii_init(adpt);
 214        if (ret)
 215                netdev_err(adpt->netdev,
 216                           "could not reinitialize internal PHY (error=%i)\n",
 217                           ret);
 218}
 219
 220static int emac_sgmii_common_open(struct emac_adapter *adpt)
 221{
 222        struct emac_sgmii *sgmii = &adpt->phy;
 223        int ret;
 224
 225        if (sgmii->irq) {
 226                /* Make sure interrupts are cleared and disabled first */
 227                ret = emac_sgmii_irq_clear(adpt, 0xff);
 228                if (ret)
 229                        return ret;
 230                writel(0, sgmii->base + EMAC_SGMII_PHY_INTERRUPT_MASK);
 231
 232                ret = request_irq(sgmii->irq, emac_sgmii_interrupt, 0,
 233                                  "emac-sgmii", adpt);
 234                if (ret) {
 235                        netdev_err(adpt->netdev,
 236                                   "could not register handler for internal PHY\n");
 237                        return ret;
 238                }
 239        }
 240
 241        return 0;
 242}
 243
 244static void emac_sgmii_common_close(struct emac_adapter *adpt)
 245{
 246        struct emac_sgmii *sgmii = &adpt->phy;
 247
 248        /* Make sure interrupts are disabled */
 249        writel(0, sgmii->base + EMAC_SGMII_PHY_INTERRUPT_MASK);
 250        free_irq(sgmii->irq, adpt);
 251}
 252
 253/* The error interrupts are only valid after the link is up */
 254static int emac_sgmii_common_link_change(struct emac_adapter *adpt, bool linkup)
 255{
 256        struct emac_sgmii *sgmii = &adpt->phy;
 257        int ret;
 258
 259        if (linkup) {
 260                /* Clear and enable interrupts */
 261                ret = emac_sgmii_irq_clear(adpt, 0xff);
 262                if (ret)
 263                        return ret;
 264
 265                writel(SGMII_ISR_MASK,
 266                       sgmii->base + EMAC_SGMII_PHY_INTERRUPT_MASK);
 267        } else {
 268                /* Disable interrupts */
 269                writel(0, sgmii->base + EMAC_SGMII_PHY_INTERRUPT_MASK);
 270                synchronize_irq(sgmii->irq);
 271        }
 272
 273        return 0;
 274}
 275
 276static struct sgmii_ops fsm9900_ops = {
 277        .init = emac_sgmii_init_fsm9900,
 278        .open = emac_sgmii_common_open,
 279        .close = emac_sgmii_common_close,
 280        .link_change = emac_sgmii_common_link_change,
 281        .reset = emac_sgmii_common_reset,
 282};
 283
 284static struct sgmii_ops qdf2432_ops = {
 285        .init = emac_sgmii_init_qdf2432,
 286        .open = emac_sgmii_common_open,
 287        .close = emac_sgmii_common_close,
 288        .link_change = emac_sgmii_common_link_change,
 289        .reset = emac_sgmii_common_reset,
 290};
 291
 292#ifdef CONFIG_ACPI
 293static struct sgmii_ops qdf2400_ops = {
 294        .init = emac_sgmii_init_qdf2400,
 295        .open = emac_sgmii_common_open,
 296        .close = emac_sgmii_common_close,
 297        .link_change = emac_sgmii_common_link_change,
 298        .reset = emac_sgmii_common_reset,
 299};
 300#endif
 301
 302static int emac_sgmii_acpi_match(struct device *dev, void *data)
 303{
 304#ifdef CONFIG_ACPI
 305        static const struct acpi_device_id match_table[] = {
 306                {
 307                        .id = "QCOM8071",
 308                },
 309                {}
 310        };
 311        const struct acpi_device_id *id = acpi_match_device(match_table, dev);
 312        struct sgmii_ops **ops = data;
 313
 314        if (id) {
 315                acpi_handle handle = ACPI_HANDLE(dev);
 316                unsigned long long hrv;
 317                acpi_status status;
 318
 319                status = acpi_evaluate_integer(handle, "_HRV", NULL, &hrv);
 320                if (status) {
 321                        if (status == AE_NOT_FOUND)
 322                                /* Older versions of the QDF2432 ACPI tables do
 323                                 * not have an _HRV property.
 324                                 */
 325                                hrv = 1;
 326                        else
 327                                /* Something is wrong with the tables */
 328                                return 0;
 329                }
 330
 331                switch (hrv) {
 332                case 1:
 333                        *ops = &qdf2432_ops;
 334                        return 1;
 335                case 2:
 336                        *ops = &qdf2400_ops;
 337                        return 1;
 338                }
 339        }
 340#endif
 341
 342        return 0;
 343}
 344
 345static const struct of_device_id emac_sgmii_dt_match[] = {
 346        {
 347                .compatible = "qcom,fsm9900-emac-sgmii",
 348                .data = &fsm9900_ops,
 349        },
 350        {
 351                .compatible = "qcom,qdf2432-emac-sgmii",
 352                .data = &qdf2432_ops,
 353        },
 354        {}
 355};
 356
 357int emac_sgmii_config(struct platform_device *pdev, struct emac_adapter *adpt)
 358{
 359        struct platform_device *sgmii_pdev = NULL;
 360        struct emac_sgmii *phy = &adpt->phy;
 361        struct resource *res;
 362        int ret;
 363
 364        if (has_acpi_companion(&pdev->dev)) {
 365                struct device *dev;
 366
 367                dev = device_find_child(&pdev->dev, &phy->sgmii_ops,
 368                                        emac_sgmii_acpi_match);
 369
 370                if (!dev) {
 371                        dev_warn(&pdev->dev, "cannot find internal phy node\n");
 372                        return 0;
 373                }
 374
 375                sgmii_pdev = to_platform_device(dev);
 376        } else {
 377                const struct of_device_id *match;
 378                struct device_node *np;
 379
 380                np = of_parse_phandle(pdev->dev.of_node, "internal-phy", 0);
 381                if (!np) {
 382                        dev_err(&pdev->dev, "missing internal-phy property\n");
 383                        return -ENODEV;
 384                }
 385
 386                sgmii_pdev = of_find_device_by_node(np);
 387                of_node_put(np);
 388                if (!sgmii_pdev) {
 389                        dev_err(&pdev->dev, "invalid internal-phy property\n");
 390                        return -ENODEV;
 391                }
 392
 393                match = of_match_device(emac_sgmii_dt_match, &sgmii_pdev->dev);
 394                if (!match) {
 395                        dev_err(&pdev->dev, "unrecognized internal phy node\n");
 396                        ret = -ENODEV;
 397                        goto error_put_device;
 398                }
 399
 400                phy->sgmii_ops = (struct sgmii_ops *)match->data;
 401        }
 402
 403        /* Base address is the first address */
 404        res = platform_get_resource(sgmii_pdev, IORESOURCE_MEM, 0);
 405        if (!res) {
 406                ret = -EINVAL;
 407                goto error_put_device;
 408        }
 409
 410        phy->base = ioremap(res->start, resource_size(res));
 411        if (!phy->base) {
 412                ret = -ENOMEM;
 413                goto error_put_device;
 414        }
 415
 416        /* v2 SGMII has a per-lane digital digital, so parse it if it exists */
 417        res = platform_get_resource(sgmii_pdev, IORESOURCE_MEM, 1);
 418        if (res) {
 419                phy->digital = ioremap(res->start, resource_size(res));
 420                if (!phy->digital) {
 421                        ret = -ENOMEM;
 422                        goto error_unmap_base;
 423                }
 424        }
 425
 426        ret = emac_sgmii_init(adpt);
 427        if (ret)
 428                goto error;
 429
 430        emac_sgmii_link_init(adpt);
 431
 432        ret = platform_get_irq(sgmii_pdev, 0);
 433        if (ret > 0)
 434                phy->irq = ret;
 435
 436        /* We've remapped the addresses, so we don't need the device any
 437         * more.  of_find_device_by_node() says we should release it.
 438         */
 439        put_device(&sgmii_pdev->dev);
 440
 441        return 0;
 442
 443error:
 444        if (phy->digital)
 445                iounmap(phy->digital);
 446error_unmap_base:
 447        iounmap(phy->base);
 448error_put_device:
 449        put_device(&sgmii_pdev->dev);
 450
 451        return ret;
 452}
 453