cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

ahci_brcm.c (15644B)


      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, __le16 *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_DEBOUNCE_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	{ /* sentinel */ }
    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
    553	brcm_sata_phys_disable(priv);
    554
    555	return ata_platform_remove_one(pdev);
    556}
    557
    558static void brcm_ahci_shutdown(struct platform_device *pdev)
    559{
    560	int ret;
    561
    562	/* All resources releasing happens via devres, but our device, unlike a
    563	 * proper remove is not disappearing, therefore using
    564	 * brcm_ahci_suspend() here which does explicit power management is
    565	 * appropriate.
    566	 */
    567	ret = brcm_ahci_suspend(&pdev->dev);
    568	if (ret)
    569		dev_err(&pdev->dev, "failed to shutdown\n");
    570}
    571
    572static SIMPLE_DEV_PM_OPS(ahci_brcm_pm_ops, brcm_ahci_suspend, brcm_ahci_resume);
    573
    574static struct platform_driver brcm_ahci_driver = {
    575	.probe = brcm_ahci_probe,
    576	.remove = brcm_ahci_remove,
    577	.shutdown = brcm_ahci_shutdown,
    578	.driver = {
    579		.name = DRV_NAME,
    580		.of_match_table = ahci_of_match,
    581		.pm = &ahci_brcm_pm_ops,
    582	},
    583};
    584module_platform_driver(brcm_ahci_driver);
    585
    586MODULE_DESCRIPTION("Broadcom SATA3 AHCI Controller Driver");
    587MODULE_AUTHOR("Brian Norris");
    588MODULE_LICENSE("GPL");
    589MODULE_ALIAS("platform:sata-brcmstb");