linux/drivers/ata/ahci_brcm.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/*
   3 * Broadcom SATA3 AHCI Controller Driver
   4 *
   5 * Copyright © 2009-2015 Broadcom Corporation
   6 */
   7
   8#include <linux/ahci_platform.h>
   9#include <linux/compiler.h>
  10#include <linux/device.h>
  11#include <linux/init.h>
  12#include <linux/interrupt.h>
  13#include <linux/io.h>
  14#include <linux/kernel.h>
  15#include <linux/libata.h>
  16#include <linux/module.h>
  17#include <linux/of.h>
  18#include <linux/platform_device.h>
  19#include <linux/reset.h>
  20#include <linux/string.h>
  21
  22#include "ahci.h"
  23
  24#define DRV_NAME                                        "brcm-ahci"
  25
  26#define SATA_TOP_CTRL_VERSION                           0x0
  27#define SATA_TOP_CTRL_BUS_CTRL                          0x4
  28 #define MMIO_ENDIAN_SHIFT                              0 /* CPU->AHCI */
  29 #define DMADESC_ENDIAN_SHIFT                           2 /* AHCI->DDR */
  30 #define DMADATA_ENDIAN_SHIFT                           4 /* AHCI->DDR */
  31 #define PIODATA_ENDIAN_SHIFT                           6
  32  #define ENDIAN_SWAP_NONE                              0
  33  #define ENDIAN_SWAP_FULL                              2
  34#define SATA_TOP_CTRL_TP_CTRL                           0x8
  35#define SATA_TOP_CTRL_PHY_CTRL                          0xc
  36 #define SATA_TOP_CTRL_PHY_CTRL_1                       0x0
  37  #define SATA_TOP_CTRL_1_PHY_DEFAULT_POWER_STATE       BIT(14)
  38 #define SATA_TOP_CTRL_PHY_CTRL_2                       0x4
  39  #define SATA_TOP_CTRL_2_SW_RST_MDIOREG                BIT(0)
  40  #define SATA_TOP_CTRL_2_SW_RST_OOB                    BIT(1)
  41  #define SATA_TOP_CTRL_2_SW_RST_RX                     BIT(2)
  42  #define SATA_TOP_CTRL_2_SW_RST_TX                     BIT(3)
  43  #define SATA_TOP_CTRL_2_PHY_GLOBAL_RESET              BIT(14)
  44 #define SATA_TOP_CTRL_PHY_OFFS                         0x8
  45 #define SATA_TOP_MAX_PHYS                              2
  46
  47#define SATA_FIRST_PORT_CTRL                            0x700
  48#define SATA_NEXT_PORT_CTRL_OFFSET                      0x80
  49#define SATA_PORT_PCTRL6(reg_base)                      (reg_base + 0x18)
  50
  51/* On big-endian MIPS, buses are reversed to big endian, so switch them back */
  52#if defined(CONFIG_MIPS) && defined(__BIG_ENDIAN)
  53#define DATA_ENDIAN                      2 /* AHCI->DDR inbound accesses */
  54#define MMIO_ENDIAN                      2 /* CPU->AHCI outbound accesses */
  55#else
  56#define DATA_ENDIAN                      0
  57#define MMIO_ENDIAN                      0
  58#endif
  59
  60#define BUS_CTRL_ENDIAN_CONF                            \
  61        ((DATA_ENDIAN << DMADATA_ENDIAN_SHIFT) |        \
  62        (DATA_ENDIAN << DMADESC_ENDIAN_SHIFT) |         \
  63        (MMIO_ENDIAN << MMIO_ENDIAN_SHIFT))
  64
  65#define BUS_CTRL_ENDIAN_NSP_CONF                        \
  66        (0x02 << DMADATA_ENDIAN_SHIFT | 0x02 << DMADESC_ENDIAN_SHIFT)
  67
  68#define BUS_CTRL_ENDIAN_CONF_MASK                       \
  69        (0x3 << MMIO_ENDIAN_SHIFT | 0x3 << DMADESC_ENDIAN_SHIFT |       \
  70         0x3 << DMADATA_ENDIAN_SHIFT | 0x3 << PIODATA_ENDIAN_SHIFT)
  71
  72enum brcm_ahci_version {
  73        BRCM_SATA_BCM7425 = 1,
  74        BRCM_SATA_BCM7445,
  75        BRCM_SATA_NSP,
  76        BRCM_SATA_BCM7216,
  77};
  78
  79enum brcm_ahci_quirks {
  80        BRCM_AHCI_QUIRK_SKIP_PHY_ENABLE = BIT(0),
  81};
  82
  83struct brcm_ahci_priv {
  84        struct device *dev;
  85        void __iomem *top_ctrl;
  86        u32 port_mask;
  87        u32 quirks;
  88        enum brcm_ahci_version version;
  89        struct reset_control *rcdev_rescal;
  90        struct reset_control *rcdev_ahci;
  91};
  92
  93static inline u32 brcm_sata_readreg(void __iomem *addr)
  94{
  95        /*
  96         * MIPS endianness is configured by boot strap, which also reverses all
  97         * bus endianness (i.e., big-endian CPU + big endian bus ==> native
  98         * endian I/O).
  99         *
 100         * Other architectures (e.g., ARM) either do not support big endian, or
 101         * else leave I/O in little endian mode.
 102         */
 103        if (IS_ENABLED(CONFIG_MIPS) && IS_ENABLED(CONFIG_CPU_BIG_ENDIAN))
 104                return __raw_readl(addr);
 105        else
 106                return readl_relaxed(addr);
 107}
 108
 109static inline void brcm_sata_writereg(u32 val, void __iomem *addr)
 110{
 111        /* See brcm_sata_readreg() comments */
 112        if (IS_ENABLED(CONFIG_MIPS) && IS_ENABLED(CONFIG_CPU_BIG_ENDIAN))
 113                __raw_writel(val, addr);
 114        else
 115                writel_relaxed(val, addr);
 116}
 117
 118static void brcm_sata_alpm_init(struct ahci_host_priv *hpriv)
 119{
 120        struct brcm_ahci_priv *priv = hpriv->plat_data;
 121        u32 port_ctrl, host_caps;
 122        int i;
 123
 124        /* Enable support for ALPM */
 125        host_caps = readl(hpriv->mmio + HOST_CAP);
 126        if (!(host_caps & HOST_CAP_ALPM))
 127                hpriv->flags |= AHCI_HFLAG_YES_ALPM;
 128
 129        /*
 130         * Adjust timeout to allow PLL sufficient time to lock while waking
 131         * up from slumber mode.
 132         */
 133        for (i = 0, port_ctrl = SATA_FIRST_PORT_CTRL;
 134             i < SATA_TOP_MAX_PHYS;
 135             i++, port_ctrl += SATA_NEXT_PORT_CTRL_OFFSET) {
 136                if (priv->port_mask & BIT(i))
 137                        writel(0xff1003fc,
 138                               hpriv->mmio + SATA_PORT_PCTRL6(port_ctrl));
 139        }
 140}
 141
 142static void brcm_sata_phy_enable(struct brcm_ahci_priv *priv, int port)
 143{
 144        void __iomem *phyctrl = priv->top_ctrl + SATA_TOP_CTRL_PHY_CTRL +
 145                                (port * SATA_TOP_CTRL_PHY_OFFS);
 146        void __iomem *p;
 147        u32 reg;
 148
 149        if (priv->quirks & BRCM_AHCI_QUIRK_SKIP_PHY_ENABLE)
 150                return;
 151
 152        /* clear PHY_DEFAULT_POWER_STATE */
 153        p = phyctrl + SATA_TOP_CTRL_PHY_CTRL_1;
 154        reg = brcm_sata_readreg(p);
 155        reg &= ~SATA_TOP_CTRL_1_PHY_DEFAULT_POWER_STATE;
 156        brcm_sata_writereg(reg, p);
 157
 158        /* reset the PHY digital logic */
 159        p = phyctrl + SATA_TOP_CTRL_PHY_CTRL_2;
 160        reg = brcm_sata_readreg(p);
 161        reg &= ~(SATA_TOP_CTRL_2_SW_RST_MDIOREG | SATA_TOP_CTRL_2_SW_RST_OOB |
 162                 SATA_TOP_CTRL_2_SW_RST_RX);
 163        reg |= SATA_TOP_CTRL_2_SW_RST_TX;
 164        brcm_sata_writereg(reg, p);
 165        reg = brcm_sata_readreg(p);
 166        reg |= SATA_TOP_CTRL_2_PHY_GLOBAL_RESET;
 167        brcm_sata_writereg(reg, p);
 168        reg = brcm_sata_readreg(p);
 169        reg &= ~SATA_TOP_CTRL_2_PHY_GLOBAL_RESET;
 170        brcm_sata_writereg(reg, p);
 171        (void)brcm_sata_readreg(p);
 172}
 173
 174static void brcm_sata_phy_disable(struct brcm_ahci_priv *priv, int port)
 175{
 176        void __iomem *phyctrl = priv->top_ctrl + SATA_TOP_CTRL_PHY_CTRL +
 177                                (port * SATA_TOP_CTRL_PHY_OFFS);
 178        void __iomem *p;
 179        u32 reg;
 180
 181        if (priv->quirks & BRCM_AHCI_QUIRK_SKIP_PHY_ENABLE)
 182                return;
 183
 184        /* power-off the PHY digital logic */
 185        p = phyctrl + SATA_TOP_CTRL_PHY_CTRL_2;
 186        reg = brcm_sata_readreg(p);
 187        reg |= (SATA_TOP_CTRL_2_SW_RST_MDIOREG | SATA_TOP_CTRL_2_SW_RST_OOB |
 188                SATA_TOP_CTRL_2_SW_RST_RX | SATA_TOP_CTRL_2_SW_RST_TX |
 189                SATA_TOP_CTRL_2_PHY_GLOBAL_RESET);
 190        brcm_sata_writereg(reg, p);
 191
 192        /* set PHY_DEFAULT_POWER_STATE */
 193        p = phyctrl + SATA_TOP_CTRL_PHY_CTRL_1;
 194        reg = brcm_sata_readreg(p);
 195        reg |= SATA_TOP_CTRL_1_PHY_DEFAULT_POWER_STATE;
 196        brcm_sata_writereg(reg, p);
 197}
 198
 199static void brcm_sata_phys_enable(struct brcm_ahci_priv *priv)
 200{
 201        int i;
 202
 203        for (i = 0; i < SATA_TOP_MAX_PHYS; i++)
 204                if (priv->port_mask & BIT(i))
 205                        brcm_sata_phy_enable(priv, i);
 206}
 207
 208static void brcm_sata_phys_disable(struct brcm_ahci_priv *priv)
 209{
 210        int i;
 211
 212        for (i = 0; i < SATA_TOP_MAX_PHYS; i++)
 213                if (priv->port_mask & BIT(i))
 214                        brcm_sata_phy_disable(priv, i);
 215}
 216
 217static u32 brcm_ahci_get_portmask(struct ahci_host_priv *hpriv,
 218                                  struct brcm_ahci_priv *priv)
 219{
 220        u32 impl;
 221
 222        impl = readl(hpriv->mmio + HOST_PORTS_IMPL);
 223
 224        if (fls(impl) > SATA_TOP_MAX_PHYS)
 225                dev_warn(priv->dev, "warning: more ports than PHYs (%#x)\n",
 226                         impl);
 227        else if (!impl)
 228                dev_info(priv->dev, "no ports found\n");
 229
 230        return impl;
 231}
 232
 233static void brcm_sata_init(struct brcm_ahci_priv *priv)
 234{
 235        void __iomem *ctrl = priv->top_ctrl + SATA_TOP_CTRL_BUS_CTRL;
 236        u32 data;
 237
 238        /* Configure endianness */
 239        data = brcm_sata_readreg(ctrl);
 240        data &= ~BUS_CTRL_ENDIAN_CONF_MASK;
 241        if (priv->version == BRCM_SATA_NSP)
 242                data |= BUS_CTRL_ENDIAN_NSP_CONF;
 243        else
 244                data |= BUS_CTRL_ENDIAN_CONF;
 245        brcm_sata_writereg(data, ctrl);
 246}
 247
 248static unsigned int brcm_ahci_read_id(struct ata_device *dev,
 249                                      struct ata_taskfile *tf, u16 *id)
 250{
 251        struct ata_port *ap = dev->link->ap;
 252        struct ata_host *host = ap->host;
 253        struct ahci_host_priv *hpriv = host->private_data;
 254        struct brcm_ahci_priv *priv = hpriv->plat_data;
 255        void __iomem *mmio = hpriv->mmio;
 256        unsigned int err_mask;
 257        unsigned long flags;
 258        int i, rc;
 259        u32 ctl;
 260
 261        /* Try to read the device ID and, if this fails, proceed with the
 262         * recovery sequence below
 263         */
 264        err_mask = ata_do_dev_read_id(dev, tf, id);
 265        if (likely(!err_mask))
 266                return err_mask;
 267
 268        /* Disable host interrupts */
 269        spin_lock_irqsave(&host->lock, flags);
 270        ctl = readl(mmio + HOST_CTL);
 271        ctl &= ~HOST_IRQ_EN;
 272        writel(ctl, mmio + HOST_CTL);
 273        readl(mmio + HOST_CTL); /* flush */
 274        spin_unlock_irqrestore(&host->lock, flags);
 275
 276        /* Perform the SATA PHY reset sequence */
 277        brcm_sata_phy_disable(priv, ap->port_no);
 278
 279        /* Reset the SATA clock */
 280        ahci_platform_disable_clks(hpriv);
 281        msleep(10);
 282
 283        ahci_platform_enable_clks(hpriv);
 284        msleep(10);
 285
 286        /* Bring the PHY back on */
 287        brcm_sata_phy_enable(priv, ap->port_no);
 288
 289        /* Re-initialize and calibrate the PHY */
 290        for (i = 0; i < hpriv->nports; i++) {
 291                rc = phy_init(hpriv->phys[i]);
 292                if (rc)
 293                        goto disable_phys;
 294
 295                rc = phy_calibrate(hpriv->phys[i]);
 296                if (rc) {
 297                        phy_exit(hpriv->phys[i]);
 298                        goto disable_phys;
 299                }
 300        }
 301
 302        /* Re-enable host interrupts */
 303        spin_lock_irqsave(&host->lock, flags);
 304        ctl = readl(mmio + HOST_CTL);
 305        ctl |= HOST_IRQ_EN;
 306        writel(ctl, mmio + HOST_CTL);
 307        readl(mmio + HOST_CTL); /* flush */
 308        spin_unlock_irqrestore(&host->lock, flags);
 309
 310        return ata_do_dev_read_id(dev, tf, id);
 311
 312disable_phys:
 313        while (--i >= 0) {
 314                phy_power_off(hpriv->phys[i]);
 315                phy_exit(hpriv->phys[i]);
 316        }
 317
 318        return AC_ERR_OTHER;
 319}
 320
 321static void brcm_ahci_host_stop(struct ata_host *host)
 322{
 323        struct ahci_host_priv *hpriv = host->private_data;
 324
 325        ahci_platform_disable_resources(hpriv);
 326}
 327
 328static struct ata_port_operations ahci_brcm_platform_ops = {
 329        .inherits       = &ahci_ops,
 330        .host_stop      = brcm_ahci_host_stop,
 331        .read_id        = brcm_ahci_read_id,
 332};
 333
 334static const struct ata_port_info ahci_brcm_port_info = {
 335        .flags          = AHCI_FLAG_COMMON | ATA_FLAG_NO_DIPM,
 336        .link_flags     = ATA_LFLAG_NO_DB_DELAY,
 337        .pio_mask       = ATA_PIO4,
 338        .udma_mask      = ATA_UDMA6,
 339        .port_ops       = &ahci_brcm_platform_ops,
 340};
 341
 342static int brcm_ahci_suspend(struct device *dev)
 343{
 344        struct ata_host *host = dev_get_drvdata(dev);
 345        struct ahci_host_priv *hpriv = host->private_data;
 346        struct brcm_ahci_priv *priv = hpriv->plat_data;
 347        int ret;
 348
 349        brcm_sata_phys_disable(priv);
 350
 351        if (IS_ENABLED(CONFIG_PM_SLEEP))
 352                ret = ahci_platform_suspend(dev);
 353        else
 354                ret = 0;
 355
 356        reset_control_assert(priv->rcdev_ahci);
 357        reset_control_rearm(priv->rcdev_rescal);
 358
 359        return ret;
 360}
 361
 362static int __maybe_unused brcm_ahci_resume(struct device *dev)
 363{
 364        struct ata_host *host = dev_get_drvdata(dev);
 365        struct ahci_host_priv *hpriv = host->private_data;
 366        struct brcm_ahci_priv *priv = hpriv->plat_data;
 367        int ret = 0;
 368
 369        ret = reset_control_deassert(priv->rcdev_ahci);
 370        if (ret)
 371                return ret;
 372        ret = reset_control_reset(priv->rcdev_rescal);
 373        if (ret)
 374                return ret;
 375
 376        /* Make sure clocks are turned on before re-configuration */
 377        ret = ahci_platform_enable_clks(hpriv);
 378        if (ret)
 379                return ret;
 380
 381        ret = ahci_platform_enable_regulators(hpriv);
 382        if (ret)
 383                goto out_disable_clks;
 384
 385        brcm_sata_init(priv);
 386        brcm_sata_phys_enable(priv);
 387        brcm_sata_alpm_init(hpriv);
 388
 389        /* Since we had to enable clocks earlier on, we cannot use
 390         * ahci_platform_resume() as-is since a second call to
 391         * ahci_platform_enable_resources() would bump up the resources
 392         * (regulators, clocks, PHYs) count artificially so we copy the part
 393         * after ahci_platform_enable_resources().
 394         */
 395        ret = ahci_platform_enable_phys(hpriv);
 396        if (ret)
 397                goto out_disable_phys;
 398
 399        ret = ahci_platform_resume_host(dev);
 400        if (ret)
 401                goto out_disable_platform_phys;
 402
 403        /* We resumed so update PM runtime state */
 404        pm_runtime_disable(dev);
 405        pm_runtime_set_active(dev);
 406        pm_runtime_enable(dev);
 407
 408        return 0;
 409
 410out_disable_platform_phys:
 411        ahci_platform_disable_phys(hpriv);
 412out_disable_phys:
 413        brcm_sata_phys_disable(priv);
 414        ahci_platform_disable_regulators(hpriv);
 415out_disable_clks:
 416        ahci_platform_disable_clks(hpriv);
 417        return ret;
 418}
 419
 420static struct scsi_host_template ahci_platform_sht = {
 421        AHCI_SHT(DRV_NAME),
 422};
 423
 424static const struct of_device_id ahci_of_match[] = {
 425        {.compatible = "brcm,bcm7425-ahci", .data = (void *)BRCM_SATA_BCM7425},
 426        {.compatible = "brcm,bcm7445-ahci", .data = (void *)BRCM_SATA_BCM7445},
 427        {.compatible = "brcm,bcm63138-ahci", .data = (void *)BRCM_SATA_BCM7445},
 428        {.compatible = "brcm,bcm-nsp-ahci", .data = (void *)BRCM_SATA_NSP},
 429        {.compatible = "brcm,bcm7216-ahci", .data = (void *)BRCM_SATA_BCM7216},
 430        {},
 431};
 432MODULE_DEVICE_TABLE(of, ahci_of_match);
 433
 434static int brcm_ahci_probe(struct platform_device *pdev)
 435{
 436        const struct of_device_id *of_id;
 437        struct device *dev = &pdev->dev;
 438        struct brcm_ahci_priv *priv;
 439        struct ahci_host_priv *hpriv;
 440        struct resource *res;
 441        int ret;
 442
 443        priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
 444        if (!priv)
 445                return -ENOMEM;
 446
 447        of_id = of_match_node(ahci_of_match, pdev->dev.of_node);
 448        if (!of_id)
 449                return -ENODEV;
 450
 451        priv->version = (enum brcm_ahci_version)of_id->data;
 452        priv->dev = dev;
 453
 454        res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "top-ctrl");
 455        priv->top_ctrl = devm_ioremap_resource(dev, res);
 456        if (IS_ERR(priv->top_ctrl))
 457                return PTR_ERR(priv->top_ctrl);
 458
 459        if (priv->version == BRCM_SATA_BCM7216) {
 460                priv->rcdev_rescal = devm_reset_control_get_optional_shared(
 461                        &pdev->dev, "rescal");
 462                if (IS_ERR(priv->rcdev_rescal))
 463                        return PTR_ERR(priv->rcdev_rescal);
 464        }
 465        priv->rcdev_ahci = devm_reset_control_get_optional(&pdev->dev, "ahci");
 466        if (IS_ERR(priv->rcdev_ahci))
 467                return PTR_ERR(priv->rcdev_ahci);
 468
 469        hpriv = ahci_platform_get_resources(pdev, 0);
 470        if (IS_ERR(hpriv))
 471                return PTR_ERR(hpriv);
 472
 473        hpriv->plat_data = priv;
 474        hpriv->flags = AHCI_HFLAG_WAKE_BEFORE_STOP | AHCI_HFLAG_NO_WRITE_TO_RO;
 475
 476        switch (priv->version) {
 477        case BRCM_SATA_BCM7425:
 478                hpriv->flags |= AHCI_HFLAG_DELAY_ENGINE;
 479                fallthrough;
 480        case BRCM_SATA_NSP:
 481                hpriv->flags |= AHCI_HFLAG_NO_NCQ;
 482                priv->quirks |= BRCM_AHCI_QUIRK_SKIP_PHY_ENABLE;
 483                break;
 484        default:
 485                break;
 486        }
 487
 488        ret = reset_control_reset(priv->rcdev_rescal);
 489        if (ret)
 490                return ret;
 491        ret = reset_control_deassert(priv->rcdev_ahci);
 492        if (ret)
 493                return ret;
 494
 495        ret = ahci_platform_enable_clks(hpriv);
 496        if (ret)
 497                goto out_reset;
 498
 499        ret = ahci_platform_enable_regulators(hpriv);
 500        if (ret)
 501                goto out_disable_clks;
 502
 503        /* Must be first so as to configure endianness including that
 504         * of the standard AHCI register space.
 505         */
 506        brcm_sata_init(priv);
 507
 508        /* Initializes priv->port_mask which is used below */
 509        priv->port_mask = brcm_ahci_get_portmask(hpriv, priv);
 510        if (!priv->port_mask) {
 511                ret = -ENODEV;
 512                goto out_disable_regulators;
 513        }
 514
 515        /* Must be done before ahci_platform_enable_phys() */
 516        brcm_sata_phys_enable(priv);
 517
 518        brcm_sata_alpm_init(hpriv);
 519
 520        ret = ahci_platform_enable_phys(hpriv);
 521        if (ret)
 522                goto out_disable_phys;
 523
 524        ret = ahci_platform_init_host(pdev, hpriv, &ahci_brcm_port_info,
 525                                      &ahci_platform_sht);
 526        if (ret)
 527                goto out_disable_platform_phys;
 528
 529        dev_info(dev, "Broadcom AHCI SATA3 registered\n");
 530
 531        return 0;
 532
 533out_disable_platform_phys:
 534        ahci_platform_disable_phys(hpriv);
 535out_disable_phys:
 536        brcm_sata_phys_disable(priv);
 537out_disable_regulators:
 538        ahci_platform_disable_regulators(hpriv);
 539out_disable_clks:
 540        ahci_platform_disable_clks(hpriv);
 541out_reset:
 542        reset_control_assert(priv->rcdev_ahci);
 543        reset_control_rearm(priv->rcdev_rescal);
 544        return ret;
 545}
 546
 547static int brcm_ahci_remove(struct platform_device *pdev)
 548{
 549        struct ata_host *host = dev_get_drvdata(&pdev->dev);
 550        struct ahci_host_priv *hpriv = host->private_data;
 551        struct brcm_ahci_priv *priv = hpriv->plat_data;
 552        int ret;
 553
 554        brcm_sata_phys_disable(priv);
 555
 556        ret = ata_platform_remove_one(pdev);
 557        if (ret)
 558                return ret;
 559
 560        return 0;
 561}
 562
 563static void brcm_ahci_shutdown(struct platform_device *pdev)
 564{
 565        int ret;
 566
 567        /* All resources releasing happens via devres, but our device, unlike a
 568         * proper remove is not disappearing, therefore using
 569         * brcm_ahci_suspend() here which does explicit power management is
 570         * appropriate.
 571         */
 572        ret = brcm_ahci_suspend(&pdev->dev);
 573        if (ret)
 574                dev_err(&pdev->dev, "failed to shutdown\n");
 575}
 576
 577static SIMPLE_DEV_PM_OPS(ahci_brcm_pm_ops, brcm_ahci_suspend, brcm_ahci_resume);
 578
 579static struct platform_driver brcm_ahci_driver = {
 580        .probe = brcm_ahci_probe,
 581        .remove = brcm_ahci_remove,
 582        .shutdown = brcm_ahci_shutdown,
 583        .driver = {
 584                .name = DRV_NAME,
 585                .of_match_table = ahci_of_match,
 586                .pm = &ahci_brcm_pm_ops,
 587        },
 588};
 589module_platform_driver(brcm_ahci_driver);
 590
 591MODULE_DESCRIPTION("Broadcom SATA3 AHCI Controller Driver");
 592MODULE_AUTHOR("Brian Norris");
 593MODULE_LICENSE("GPL");
 594MODULE_ALIAS("platform:sata-brcmstb");
 595