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