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