linux/drivers/ata/ahci_platform.c
<<
>>
Prefs
   1/*
   2 * AHCI SATA platform driver
   3 *
   4 * Copyright 2004-2005  Red Hat, Inc.
   5 *   Jeff Garzik <jgarzik@pobox.com>
   6 * Copyright 2010  MontaVista Software, LLC.
   7 *   Anton Vorontsov <avorontsov@ru.mvista.com>
   8 *
   9 * This program is free software; you can redistribute it and/or modify
  10 * it under the terms of the GNU General Public License as published by
  11 * the Free Software Foundation; either version 2, or (at your option)
  12 * any later version.
  13 */
  14
  15#include <linux/kernel.h>
  16#include <linux/gfp.h>
  17#include <linux/module.h>
  18#include <linux/init.h>
  19#include <linux/interrupt.h>
  20#include <linux/device.h>
  21#include <linux/platform_device.h>
  22#include <linux/libata.h>
  23#include <linux/ahci_platform.h>
  24#include "ahci.h"
  25
  26enum ahci_type {
  27        AHCI,           /* standard platform ahci */
  28        IMX53_AHCI,     /* ahci on i.mx53 */
  29        STRICT_AHCI,    /* delayed DMA engine start */
  30};
  31
  32static struct platform_device_id ahci_devtype[] = {
  33        {
  34                .name = "ahci",
  35                .driver_data = AHCI,
  36        }, {
  37                .name = "imx53-ahci",
  38                .driver_data = IMX53_AHCI,
  39        }, {
  40                .name = "strict-ahci",
  41                .driver_data = STRICT_AHCI,
  42        }, {
  43                /* sentinel */
  44        }
  45};
  46MODULE_DEVICE_TABLE(platform, ahci_devtype);
  47
  48
  49static const struct ata_port_info ahci_port_info[] = {
  50        /* by features */
  51        [AHCI] = {
  52                .flags          = AHCI_FLAG_COMMON,
  53                .pio_mask       = ATA_PIO4,
  54                .udma_mask      = ATA_UDMA6,
  55                .port_ops       = &ahci_ops,
  56        },
  57        [IMX53_AHCI] = {
  58                .flags          = AHCI_FLAG_COMMON,
  59                .pio_mask       = ATA_PIO4,
  60                .udma_mask      = ATA_UDMA6,
  61                .port_ops       = &ahci_pmp_retry_srst_ops,
  62        },
  63        [STRICT_AHCI] = {
  64                AHCI_HFLAGS     (AHCI_HFLAG_DELAY_ENGINE),
  65                .flags          = AHCI_FLAG_COMMON,
  66                .pio_mask       = ATA_PIO4,
  67                .udma_mask      = ATA_UDMA6,
  68                .port_ops       = &ahci_ops,
  69        },
  70};
  71
  72static struct scsi_host_template ahci_platform_sht = {
  73        AHCI_SHT("ahci_platform"),
  74};
  75
  76static int __init ahci_probe(struct platform_device *pdev)
  77{
  78        struct device *dev = &pdev->dev;
  79        struct ahci_platform_data *pdata = dev_get_platdata(dev);
  80        const struct platform_device_id *id = platform_get_device_id(pdev);
  81        struct ata_port_info pi = ahci_port_info[id ? id->driver_data : 0];
  82        const struct ata_port_info *ppi[] = { &pi, NULL };
  83        struct ahci_host_priv *hpriv;
  84        struct ata_host *host;
  85        struct resource *mem;
  86        int irq;
  87        int n_ports;
  88        int i;
  89        int rc;
  90
  91        mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
  92        if (!mem) {
  93                dev_err(dev, "no mmio space\n");
  94                return -EINVAL;
  95        }
  96
  97        irq = platform_get_irq(pdev, 0);
  98        if (irq <= 0) {
  99                dev_err(dev, "no irq\n");
 100                return -EINVAL;
 101        }
 102
 103        if (pdata && pdata->ata_port_info)
 104                pi = *pdata->ata_port_info;
 105
 106        hpriv = devm_kzalloc(dev, sizeof(*hpriv), GFP_KERNEL);
 107        if (!hpriv) {
 108                dev_err(dev, "can't alloc ahci_host_priv\n");
 109                return -ENOMEM;
 110        }
 111
 112        hpriv->flags |= (unsigned long)pi.private_data;
 113
 114        hpriv->mmio = devm_ioremap(dev, mem->start, resource_size(mem));
 115        if (!hpriv->mmio) {
 116                dev_err(dev, "can't map %pR\n", mem);
 117                return -ENOMEM;
 118        }
 119
 120        /*
 121         * Some platforms might need to prepare for mmio region access,
 122         * which could be done in the following init call. So, the mmio
 123         * region shouldn't be accessed before init (if provided) has
 124         * returned successfully.
 125         */
 126        if (pdata && pdata->init) {
 127                rc = pdata->init(dev, hpriv->mmio);
 128                if (rc)
 129                        return rc;
 130        }
 131
 132        ahci_save_initial_config(dev, hpriv,
 133                pdata ? pdata->force_port_map : 0,
 134                pdata ? pdata->mask_port_map  : 0);
 135
 136        /* prepare host */
 137        if (hpriv->cap & HOST_CAP_NCQ)
 138                pi.flags |= ATA_FLAG_NCQ;
 139
 140        if (hpriv->cap & HOST_CAP_PMP)
 141                pi.flags |= ATA_FLAG_PMP;
 142
 143        ahci_set_em_messages(hpriv, &pi);
 144
 145        /* CAP.NP sometimes indicate the index of the last enabled
 146         * port, at other times, that of the last possible port, so
 147         * determining the maximum port number requires looking at
 148         * both CAP.NP and port_map.
 149         */
 150        n_ports = max(ahci_nr_ports(hpriv->cap), fls(hpriv->port_map));
 151
 152        host = ata_host_alloc_pinfo(dev, ppi, n_ports);
 153        if (!host) {
 154                rc = -ENOMEM;
 155                goto err0;
 156        }
 157
 158        host->private_data = hpriv;
 159
 160        if (!(hpriv->cap & HOST_CAP_SSS) || ahci_ignore_sss)
 161                host->flags |= ATA_HOST_PARALLEL_SCAN;
 162        else
 163                printk(KERN_INFO "ahci: SSS flag set, parallel bus scan disabled\n");
 164
 165        if (pi.flags & ATA_FLAG_EM)
 166                ahci_reset_em(host);
 167
 168        for (i = 0; i < host->n_ports; i++) {
 169                struct ata_port *ap = host->ports[i];
 170
 171                ata_port_desc(ap, "mmio %pR", mem);
 172                ata_port_desc(ap, "port 0x%x", 0x100 + ap->port_no * 0x80);
 173
 174                /* set enclosure management message type */
 175                if (ap->flags & ATA_FLAG_EM)
 176                        ap->em_message_type = hpriv->em_msg_type;
 177
 178                /* disabled/not-implemented port */
 179                if (!(hpriv->port_map & (1 << i)))
 180                        ap->ops = &ata_dummy_port_ops;
 181        }
 182
 183        rc = ahci_reset_controller(host);
 184        if (rc)
 185                goto err0;
 186
 187        ahci_init_controller(host);
 188        ahci_print_info(host, "platform");
 189
 190        rc = ata_host_activate(host, irq, ahci_interrupt, IRQF_SHARED,
 191                               &ahci_platform_sht);
 192        if (rc)
 193                goto err0;
 194
 195        return 0;
 196err0:
 197        if (pdata && pdata->exit)
 198                pdata->exit(dev);
 199        return rc;
 200}
 201
 202static int __devexit ahci_remove(struct platform_device *pdev)
 203{
 204        struct device *dev = &pdev->dev;
 205        struct ahci_platform_data *pdata = dev_get_platdata(dev);
 206        struct ata_host *host = dev_get_drvdata(dev);
 207
 208        ata_host_detach(host);
 209
 210        if (pdata && pdata->exit)
 211                pdata->exit(dev);
 212
 213        return 0;
 214}
 215
 216#ifdef CONFIG_PM
 217static int ahci_suspend(struct device *dev)
 218{
 219        struct ahci_platform_data *pdata = dev_get_platdata(dev);
 220        struct ata_host *host = dev_get_drvdata(dev);
 221        struct ahci_host_priv *hpriv = host->private_data;
 222        void __iomem *mmio = hpriv->mmio;
 223        u32 ctl;
 224        int rc;
 225
 226        if (hpriv->flags & AHCI_HFLAG_NO_SUSPEND) {
 227                dev_err(dev, "firmware update required for suspend/resume\n");
 228                return -EIO;
 229        }
 230
 231        /*
 232         * AHCI spec rev1.1 section 8.3.3:
 233         * Software must disable interrupts prior to requesting a
 234         * transition of the HBA to D3 state.
 235         */
 236        ctl = readl(mmio + HOST_CTL);
 237        ctl &= ~HOST_IRQ_EN;
 238        writel(ctl, mmio + HOST_CTL);
 239        readl(mmio + HOST_CTL); /* flush */
 240
 241        rc = ata_host_suspend(host, PMSG_SUSPEND);
 242        if (rc)
 243                return rc;
 244
 245        if (pdata && pdata->suspend)
 246                return pdata->suspend(dev);
 247        return 0;
 248}
 249
 250static int ahci_resume(struct device *dev)
 251{
 252        struct ahci_platform_data *pdata = dev_get_platdata(dev);
 253        struct ata_host *host = dev_get_drvdata(dev);
 254        int rc;
 255
 256        if (pdata && pdata->resume) {
 257                rc = pdata->resume(dev);
 258                if (rc)
 259                        return rc;
 260        }
 261
 262        if (dev->power.power_state.event == PM_EVENT_SUSPEND) {
 263                rc = ahci_reset_controller(host);
 264                if (rc)
 265                        return rc;
 266
 267                ahci_init_controller(host);
 268        }
 269
 270        ata_host_resume(host);
 271
 272        return 0;
 273}
 274
 275static struct dev_pm_ops ahci_pm_ops = {
 276        .suspend                = &ahci_suspend,
 277        .resume                 = &ahci_resume,
 278};
 279#endif
 280
 281static const struct of_device_id ahci_of_match[] = {
 282        { .compatible = "calxeda,hb-ahci", },
 283        {},
 284};
 285MODULE_DEVICE_TABLE(of, ahci_of_match);
 286
 287static struct platform_driver ahci_driver = {
 288        .remove = __devexit_p(ahci_remove),
 289        .driver = {
 290                .name = "ahci",
 291                .owner = THIS_MODULE,
 292                .of_match_table = ahci_of_match,
 293#ifdef CONFIG_PM
 294                .pm = &ahci_pm_ops,
 295#endif
 296        },
 297        .id_table       = ahci_devtype,
 298};
 299
 300static int __init ahci_init(void)
 301{
 302        return platform_driver_probe(&ahci_driver, ahci_probe);
 303}
 304module_init(ahci_init);
 305
 306static void __exit ahci_exit(void)
 307{
 308        platform_driver_unregister(&ahci_driver);
 309}
 310module_exit(ahci_exit);
 311
 312MODULE_DESCRIPTION("AHCI SATA platform driver");
 313MODULE_AUTHOR("Anton Vorontsov <avorontsov@ru.mvista.com>");
 314MODULE_LICENSE("GPL");
 315MODULE_ALIAS("platform:ahci");
 316