linux/drivers/ata/ahci_brcm.c
<<
>>
Prefs
   1/*
   2 * Broadcom SATA3 AHCI Controller Driver
   3 *
   4 * Copyright © 2009-2015 Broadcom Corporation
   5 *
   6 * This program is free software; you can redistribute it and/or modify
   7 * it under the terms of the GNU General Public License as published by
   8 * the Free Software Foundation; either version 2, or (at your option)
   9 * any later version.
  10 *
  11 * This program is distributed in the hope that it will be useful,
  12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14 * GNU General Public License for more details.
  15 */
  16
  17#include <linux/ahci_platform.h>
  18#include <linux/compiler.h>
  19#include <linux/device.h>
  20#include <linux/init.h>
  21#include <linux/interrupt.h>
  22#include <linux/io.h>
  23#include <linux/kernel.h>
  24#include <linux/libata.h>
  25#include <linux/module.h>
  26#include <linux/of.h>
  27#include <linux/platform_device.h>
  28#include <linux/string.h>
  29
  30#include "ahci.h"
  31
  32#define DRV_NAME                                        "brcm-ahci"
  33
  34#define SATA_TOP_CTRL_VERSION                           0x0
  35#define SATA_TOP_CTRL_BUS_CTRL                          0x4
  36 #define MMIO_ENDIAN_SHIFT                              0 /* CPU->AHCI */
  37 #define DMADESC_ENDIAN_SHIFT                           2 /* AHCI->DDR */
  38 #define DMADATA_ENDIAN_SHIFT                           4 /* AHCI->DDR */
  39 #define PIODATA_ENDIAN_SHIFT                           6
  40  #define ENDIAN_SWAP_NONE                              0
  41  #define ENDIAN_SWAP_FULL                              2
  42#define SATA_TOP_CTRL_TP_CTRL                           0x8
  43#define SATA_TOP_CTRL_PHY_CTRL                          0xc
  44 #define SATA_TOP_CTRL_PHY_CTRL_1                       0x0
  45  #define SATA_TOP_CTRL_1_PHY_DEFAULT_POWER_STATE       BIT(14)
  46 #define SATA_TOP_CTRL_PHY_CTRL_2                       0x4
  47  #define SATA_TOP_CTRL_2_SW_RST_MDIOREG                BIT(0)
  48  #define SATA_TOP_CTRL_2_SW_RST_OOB                    BIT(1)
  49  #define SATA_TOP_CTRL_2_SW_RST_RX                     BIT(2)
  50  #define SATA_TOP_CTRL_2_SW_RST_TX                     BIT(3)
  51  #define SATA_TOP_CTRL_2_PHY_GLOBAL_RESET              BIT(14)
  52 #define SATA_TOP_CTRL_PHY_OFFS                         0x8
  53 #define SATA_TOP_MAX_PHYS                              2
  54
  55#define SATA_FIRST_PORT_CTRL                            0x700
  56#define SATA_NEXT_PORT_CTRL_OFFSET                      0x80
  57#define SATA_PORT_PCTRL6(reg_base)                      (reg_base + 0x18)
  58
  59/* On big-endian MIPS, buses are reversed to big endian, so switch them back */
  60#if defined(CONFIG_MIPS) && defined(__BIG_ENDIAN)
  61#define DATA_ENDIAN                      2 /* AHCI->DDR inbound accesses */
  62#define MMIO_ENDIAN                      2 /* CPU->AHCI outbound accesses */
  63#else
  64#define DATA_ENDIAN                      0
  65#define MMIO_ENDIAN                      0
  66#endif
  67
  68#define BUS_CTRL_ENDIAN_CONF                            \
  69        ((DATA_ENDIAN << DMADATA_ENDIAN_SHIFT) |        \
  70        (DATA_ENDIAN << DMADESC_ENDIAN_SHIFT) |         \
  71        (MMIO_ENDIAN << MMIO_ENDIAN_SHIFT))
  72
  73#define BUS_CTRL_ENDIAN_NSP_CONF                        \
  74        (0x02 << DMADATA_ENDIAN_SHIFT | 0x02 << DMADESC_ENDIAN_SHIFT)
  75
  76#define BUS_CTRL_ENDIAN_CONF_MASK                       \
  77        (0x3 << MMIO_ENDIAN_SHIFT | 0x3 << DMADESC_ENDIAN_SHIFT |       \
  78         0x3 << DMADATA_ENDIAN_SHIFT | 0x3 << PIODATA_ENDIAN_SHIFT)
  79
  80enum brcm_ahci_version {
  81        BRCM_SATA_BCM7425 = 1,
  82        BRCM_SATA_BCM7445,
  83        BRCM_SATA_NSP,
  84};
  85
  86enum brcm_ahci_quirks {
  87        BRCM_AHCI_QUIRK_NO_NCQ          = BIT(0),
  88        BRCM_AHCI_QUIRK_SKIP_PHY_ENABLE = BIT(1),
  89};
  90
  91struct brcm_ahci_priv {
  92        struct device *dev;
  93        void __iomem *top_ctrl;
  94        u32 port_mask;
  95        u32 quirks;
  96        enum brcm_ahci_version version;
  97};
  98
  99static inline u32 brcm_sata_readreg(void __iomem *addr)
 100{
 101        /*
 102         * MIPS endianness is configured by boot strap, which also reverses all
 103         * bus endianness (i.e., big-endian CPU + big endian bus ==> native
 104         * endian I/O).
 105         *
 106         * Other architectures (e.g., ARM) either do not support big endian, or
 107         * else leave I/O in little endian mode.
 108         */
 109        if (IS_ENABLED(CONFIG_MIPS) && IS_ENABLED(CONFIG_CPU_BIG_ENDIAN))
 110                return __raw_readl(addr);
 111        else
 112                return readl_relaxed(addr);
 113}
 114
 115static inline void brcm_sata_writereg(u32 val, void __iomem *addr)
 116{
 117        /* See brcm_sata_readreg() comments */
 118        if (IS_ENABLED(CONFIG_MIPS) && IS_ENABLED(CONFIG_CPU_BIG_ENDIAN))
 119                __raw_writel(val, addr);
 120        else
 121                writel_relaxed(val, addr);
 122}
 123
 124static void brcm_sata_alpm_init(struct ahci_host_priv *hpriv)
 125{
 126        struct brcm_ahci_priv *priv = hpriv->plat_data;
 127        u32 port_ctrl, host_caps;
 128        int i;
 129
 130        /* Enable support for ALPM */
 131        host_caps = readl(hpriv->mmio + HOST_CAP);
 132        if (!(host_caps & HOST_CAP_ALPM))
 133                hpriv->flags |= AHCI_HFLAG_YES_ALPM;
 134
 135        /*
 136         * Adjust timeout to allow PLL sufficient time to lock while waking
 137         * up from slumber mode.
 138         */
 139        for (i = 0, port_ctrl = SATA_FIRST_PORT_CTRL;
 140             i < SATA_TOP_MAX_PHYS;
 141             i++, port_ctrl += SATA_NEXT_PORT_CTRL_OFFSET) {
 142                if (priv->port_mask & BIT(i))
 143                        writel(0xff1003fc,
 144                               hpriv->mmio + SATA_PORT_PCTRL6(port_ctrl));
 145        }
 146}
 147
 148static void brcm_sata_phy_enable(struct brcm_ahci_priv *priv, int port)
 149{
 150        void __iomem *phyctrl = priv->top_ctrl + SATA_TOP_CTRL_PHY_CTRL +
 151                                (port * SATA_TOP_CTRL_PHY_OFFS);
 152        void __iomem *p;
 153        u32 reg;
 154
 155        if (priv->quirks & BRCM_AHCI_QUIRK_SKIP_PHY_ENABLE)
 156                return;
 157
 158        /* clear PHY_DEFAULT_POWER_STATE */
 159        p = phyctrl + SATA_TOP_CTRL_PHY_CTRL_1;
 160        reg = brcm_sata_readreg(p);
 161        reg &= ~SATA_TOP_CTRL_1_PHY_DEFAULT_POWER_STATE;
 162        brcm_sata_writereg(reg, p);
 163
 164        /* reset the PHY digital logic */
 165        p = phyctrl + SATA_TOP_CTRL_PHY_CTRL_2;
 166        reg = brcm_sata_readreg(p);
 167        reg &= ~(SATA_TOP_CTRL_2_SW_RST_MDIOREG | SATA_TOP_CTRL_2_SW_RST_OOB |
 168                 SATA_TOP_CTRL_2_SW_RST_RX);
 169        reg |= SATA_TOP_CTRL_2_SW_RST_TX;
 170        brcm_sata_writereg(reg, p);
 171        reg = brcm_sata_readreg(p);
 172        reg |= SATA_TOP_CTRL_2_PHY_GLOBAL_RESET;
 173        brcm_sata_writereg(reg, p);
 174        reg = brcm_sata_readreg(p);
 175        reg &= ~SATA_TOP_CTRL_2_PHY_GLOBAL_RESET;
 176        brcm_sata_writereg(reg, p);
 177        (void)brcm_sata_readreg(p);
 178}
 179
 180static void brcm_sata_phy_disable(struct brcm_ahci_priv *priv, int port)
 181{
 182        void __iomem *phyctrl = priv->top_ctrl + SATA_TOP_CTRL_PHY_CTRL +
 183                                (port * SATA_TOP_CTRL_PHY_OFFS);
 184        void __iomem *p;
 185        u32 reg;
 186
 187        if (priv->quirks & BRCM_AHCI_QUIRK_SKIP_PHY_ENABLE)
 188                return;
 189
 190        /* power-off the PHY digital logic */
 191        p = phyctrl + SATA_TOP_CTRL_PHY_CTRL_2;
 192        reg = brcm_sata_readreg(p);
 193        reg |= (SATA_TOP_CTRL_2_SW_RST_MDIOREG | SATA_TOP_CTRL_2_SW_RST_OOB |
 194                SATA_TOP_CTRL_2_SW_RST_RX | SATA_TOP_CTRL_2_SW_RST_TX |
 195                SATA_TOP_CTRL_2_PHY_GLOBAL_RESET);
 196        brcm_sata_writereg(reg, p);
 197
 198        /* set PHY_DEFAULT_POWER_STATE */
 199        p = phyctrl + SATA_TOP_CTRL_PHY_CTRL_1;
 200        reg = brcm_sata_readreg(p);
 201        reg |= SATA_TOP_CTRL_1_PHY_DEFAULT_POWER_STATE;
 202        brcm_sata_writereg(reg, p);
 203}
 204
 205static void brcm_sata_phys_enable(struct brcm_ahci_priv *priv)
 206{
 207        int i;
 208
 209        for (i = 0; i < SATA_TOP_MAX_PHYS; i++)
 210                if (priv->port_mask & BIT(i))
 211                        brcm_sata_phy_enable(priv, i);
 212}
 213
 214static void brcm_sata_phys_disable(struct brcm_ahci_priv *priv)
 215{
 216        int i;
 217
 218        for (i = 0; i < SATA_TOP_MAX_PHYS; i++)
 219                if (priv->port_mask & BIT(i))
 220                        brcm_sata_phy_disable(priv, i);
 221}
 222
 223static u32 brcm_ahci_get_portmask(struct platform_device *pdev,
 224                                  struct brcm_ahci_priv *priv)
 225{
 226        void __iomem *ahci;
 227        struct resource *res;
 228        u32 impl;
 229
 230        res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "ahci");
 231        ahci = devm_ioremap_resource(&pdev->dev, res);
 232        if (IS_ERR(ahci))
 233                return 0;
 234
 235        impl = readl(ahci + HOST_PORTS_IMPL);
 236
 237        if (fls(impl) > SATA_TOP_MAX_PHYS)
 238                dev_warn(priv->dev, "warning: more ports than PHYs (%#x)\n",
 239                         impl);
 240        else if (!impl)
 241                dev_info(priv->dev, "no ports found\n");
 242
 243        devm_iounmap(&pdev->dev, ahci);
 244        devm_release_mem_region(&pdev->dev, res->start, resource_size(res));
 245
 246        return impl;
 247}
 248
 249static void brcm_sata_init(struct brcm_ahci_priv *priv)
 250{
 251        void __iomem *ctrl = priv->top_ctrl + SATA_TOP_CTRL_BUS_CTRL;
 252        u32 data;
 253
 254        /* Configure endianness */
 255        data = brcm_sata_readreg(ctrl);
 256        data &= ~BUS_CTRL_ENDIAN_CONF_MASK;
 257        if (priv->version == BRCM_SATA_NSP)
 258                data |= BUS_CTRL_ENDIAN_NSP_CONF;
 259        else
 260                data |= BUS_CTRL_ENDIAN_CONF;
 261        brcm_sata_writereg(data, ctrl);
 262}
 263
 264static unsigned int brcm_ahci_read_id(struct ata_device *dev,
 265                                      struct ata_taskfile *tf, u16 *id)
 266{
 267        struct ata_port *ap = dev->link->ap;
 268        struct ata_host *host = ap->host;
 269        struct ahci_host_priv *hpriv = host->private_data;
 270        struct brcm_ahci_priv *priv = hpriv->plat_data;
 271        void __iomem *mmio = hpriv->mmio;
 272        unsigned int err_mask;
 273        unsigned long flags;
 274        int i, rc;
 275        u32 ctl;
 276
 277        /* Try to read the device ID and, if this fails, proceed with the
 278         * recovery sequence below
 279         */
 280        err_mask = ata_do_dev_read_id(dev, tf, id);
 281        if (likely(!err_mask))
 282                return err_mask;
 283
 284        /* Disable host interrupts */
 285        spin_lock_irqsave(&host->lock, flags);
 286        ctl = readl(mmio + HOST_CTL);
 287        ctl &= ~HOST_IRQ_EN;
 288        writel(ctl, mmio + HOST_CTL);
 289        readl(mmio + HOST_CTL); /* flush */
 290        spin_unlock_irqrestore(&host->lock, flags);
 291
 292        /* Perform the SATA PHY reset sequence */
 293        brcm_sata_phy_disable(priv, ap->port_no);
 294
 295        /* Bring the PHY back on */
 296        brcm_sata_phy_enable(priv, ap->port_no);
 297
 298        /* Re-initialize and calibrate the PHY */
 299        for (i = 0; i < hpriv->nports; i++) {
 300                rc = phy_init(hpriv->phys[i]);
 301                if (rc)
 302                        goto disable_phys;
 303
 304                rc = phy_calibrate(hpriv->phys[i]);
 305                if (rc) {
 306                        phy_exit(hpriv->phys[i]);
 307                        goto disable_phys;
 308                }
 309        }
 310
 311        /* Re-enable host interrupts */
 312        spin_lock_irqsave(&host->lock, flags);
 313        ctl = readl(mmio + HOST_CTL);
 314        ctl |= HOST_IRQ_EN;
 315        writel(ctl, mmio + HOST_CTL);
 316        readl(mmio + HOST_CTL); /* flush */
 317        spin_unlock_irqrestore(&host->lock, flags);
 318
 319        return ata_do_dev_read_id(dev, tf, id);
 320
 321disable_phys:
 322        while (--i >= 0) {
 323                phy_power_off(hpriv->phys[i]);
 324                phy_exit(hpriv->phys[i]);
 325        }
 326
 327        return AC_ERR_OTHER;
 328}
 329
 330static void brcm_ahci_host_stop(struct ata_host *host)
 331{
 332        struct ahci_host_priv *hpriv = host->private_data;
 333
 334        ahci_platform_disable_resources(hpriv);
 335}
 336
 337static struct ata_port_operations ahci_brcm_platform_ops = {
 338        .inherits       = &ahci_ops,
 339        .host_stop      = brcm_ahci_host_stop,
 340        .read_id        = brcm_ahci_read_id,
 341};
 342
 343static const struct ata_port_info ahci_brcm_port_info = {
 344        .flags          = AHCI_FLAG_COMMON | ATA_FLAG_NO_DIPM,
 345        .link_flags     = ATA_LFLAG_NO_DB_DELAY,
 346        .pio_mask       = ATA_PIO4,
 347        .udma_mask      = ATA_UDMA6,
 348        .port_ops       = &ahci_brcm_platform_ops,
 349};
 350
 351#ifdef CONFIG_PM_SLEEP
 352static int brcm_ahci_suspend(struct device *dev)
 353{
 354        struct ata_host *host = dev_get_drvdata(dev);
 355        struct ahci_host_priv *hpriv = host->private_data;
 356        struct brcm_ahci_priv *priv = hpriv->plat_data;
 357        int ret;
 358
 359        ret = ahci_platform_suspend(dev);
 360        brcm_sata_phys_disable(priv);
 361        return ret;
 362}
 363
 364static int brcm_ahci_resume(struct device *dev)
 365{
 366        struct ata_host *host = dev_get_drvdata(dev);
 367        struct ahci_host_priv *hpriv = host->private_data;
 368        struct brcm_ahci_priv *priv = hpriv->plat_data;
 369
 370        brcm_sata_init(priv);
 371        brcm_sata_phys_enable(priv);
 372        brcm_sata_alpm_init(hpriv);
 373        return ahci_platform_resume(dev);
 374}
 375#endif
 376
 377static struct scsi_host_template ahci_platform_sht = {
 378        AHCI_SHT(DRV_NAME),
 379};
 380
 381static const struct of_device_id ahci_of_match[] = {
 382        {.compatible = "brcm,bcm7425-ahci", .data = (void *)BRCM_SATA_BCM7425},
 383        {.compatible = "brcm,bcm7445-ahci", .data = (void *)BRCM_SATA_BCM7445},
 384        {.compatible = "brcm,bcm-nsp-ahci", .data = (void *)BRCM_SATA_NSP},
 385        {},
 386};
 387MODULE_DEVICE_TABLE(of, ahci_of_match);
 388
 389static int brcm_ahci_probe(struct platform_device *pdev)
 390{
 391        const struct of_device_id *of_id;
 392        struct device *dev = &pdev->dev;
 393        struct brcm_ahci_priv *priv;
 394        struct ahci_host_priv *hpriv;
 395        struct resource *res;
 396        int ret;
 397
 398        priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
 399        if (!priv)
 400                return -ENOMEM;
 401
 402        of_id = of_match_node(ahci_of_match, pdev->dev.of_node);
 403        if (!of_id)
 404                return -ENODEV;
 405
 406        priv->version = (enum brcm_ahci_version)of_id->data;
 407        priv->dev = dev;
 408
 409        res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "top-ctrl");
 410        priv->top_ctrl = devm_ioremap_resource(dev, res);
 411        if (IS_ERR(priv->top_ctrl))
 412                return PTR_ERR(priv->top_ctrl);
 413
 414        if ((priv->version == BRCM_SATA_BCM7425) ||
 415                (priv->version == BRCM_SATA_NSP)) {
 416                priv->quirks |= BRCM_AHCI_QUIRK_NO_NCQ;
 417                priv->quirks |= BRCM_AHCI_QUIRK_SKIP_PHY_ENABLE;
 418        }
 419
 420        brcm_sata_init(priv);
 421
 422        priv->port_mask = brcm_ahci_get_portmask(pdev, priv);
 423        if (!priv->port_mask)
 424                return -ENODEV;
 425
 426        brcm_sata_phys_enable(priv);
 427
 428        hpriv = ahci_platform_get_resources(pdev);
 429        if (IS_ERR(hpriv))
 430                return PTR_ERR(hpriv);
 431        hpriv->plat_data = priv;
 432        hpriv->flags = AHCI_HFLAG_WAKE_BEFORE_STOP;
 433
 434        brcm_sata_alpm_init(hpriv);
 435
 436        ret = ahci_platform_enable_resources(hpriv);
 437        if (ret)
 438                return ret;
 439
 440        if (priv->quirks & BRCM_AHCI_QUIRK_NO_NCQ)
 441                hpriv->flags |= AHCI_HFLAG_NO_NCQ;
 442        hpriv->flags |= AHCI_HFLAG_NO_WRITE_TO_RO;
 443
 444        ret = ahci_platform_init_host(pdev, hpriv, &ahci_brcm_port_info,
 445                                      &ahci_platform_sht);
 446        if (ret)
 447                return ret;
 448
 449        dev_info(dev, "Broadcom AHCI SATA3 registered\n");
 450
 451        return 0;
 452}
 453
 454static int brcm_ahci_remove(struct platform_device *pdev)
 455{
 456        struct ata_host *host = dev_get_drvdata(&pdev->dev);
 457        struct ahci_host_priv *hpriv = host->private_data;
 458        struct brcm_ahci_priv *priv = hpriv->plat_data;
 459        int ret;
 460
 461        ret = ata_platform_remove_one(pdev);
 462        if (ret)
 463                return ret;
 464
 465        brcm_sata_phys_disable(priv);
 466
 467        return 0;
 468}
 469
 470static SIMPLE_DEV_PM_OPS(ahci_brcm_pm_ops, brcm_ahci_suspend, brcm_ahci_resume);
 471
 472static struct platform_driver brcm_ahci_driver = {
 473        .probe = brcm_ahci_probe,
 474        .remove = brcm_ahci_remove,
 475        .driver = {
 476                .name = DRV_NAME,
 477                .of_match_table = ahci_of_match,
 478                .pm = &ahci_brcm_pm_ops,
 479        },
 480};
 481module_platform_driver(brcm_ahci_driver);
 482
 483MODULE_DESCRIPTION("Broadcom SATA3 AHCI Controller Driver");
 484MODULE_AUTHOR("Brian Norris");
 485MODULE_LICENSE("GPL");
 486MODULE_ALIAS("platform:sata-brcmstb");
 487