linux/drivers/mmc/host/sdhci-pltfm.c
<<
>>
Prefs
   1/*
   2 * sdhci-pltfm.c Support for SDHCI platform devices
   3 * Copyright (c) 2009 Intel Corporation
   4 *
   5 * This program is free software; you can redistribute it and/or modify
   6 * it under the terms of the GNU General Public License version 2 as
   7 * published by the Free Software Foundation.
   8 *
   9 * This program is distributed in the hope that it will be useful,
  10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12 * GNU General Public License for more details.
  13 *
  14 * You should have received a copy of the GNU General Public License
  15 * along with this program; if not, write to the Free Software
  16 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  17 */
  18
  19/* Supports:
  20 * SDHCI platform devices
  21 *
  22 * Inspired by sdhci-pci.c, by Pierre Ossman
  23 */
  24
  25#include <linux/delay.h>
  26#include <linux/highmem.h>
  27#include <linux/platform_device.h>
  28
  29#include <linux/mmc/host.h>
  30
  31#include <linux/io.h>
  32
  33#include "sdhci.h"
  34
  35/*****************************************************************************\
  36 *                                                                           *
  37 * SDHCI core callbacks                                                      *
  38 *                                                                           *
  39\*****************************************************************************/
  40
  41static struct sdhci_ops sdhci_pltfm_ops = {
  42};
  43
  44/*****************************************************************************\
  45 *                                                                           *
  46 * Device probing/removal                                                    *
  47 *                                                                           *
  48\*****************************************************************************/
  49
  50static int __devinit sdhci_pltfm_probe(struct platform_device *pdev)
  51{
  52        struct sdhci_host *host;
  53        struct resource *iomem;
  54        int ret;
  55
  56        BUG_ON(pdev == NULL);
  57
  58        iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
  59        if (!iomem) {
  60                ret = -ENOMEM;
  61                goto err;
  62        }
  63
  64        if (resource_size(iomem) != 0x100)
  65                dev_err(&pdev->dev, "Invalid iomem size. You may "
  66                        "experience problems.\n");
  67
  68        if (pdev->dev.parent)
  69                host = sdhci_alloc_host(pdev->dev.parent, 0);
  70        else
  71                host = sdhci_alloc_host(&pdev->dev, 0);
  72
  73        if (IS_ERR(host)) {
  74                ret = PTR_ERR(host);
  75                goto err;
  76        }
  77
  78        host->hw_name = "platform";
  79        host->ops = &sdhci_pltfm_ops;
  80        host->irq = platform_get_irq(pdev, 0);
  81
  82        if (!request_mem_region(iomem->start, resource_size(iomem),
  83                mmc_hostname(host->mmc))) {
  84                dev_err(&pdev->dev, "cannot request region\n");
  85                ret = -EBUSY;
  86                goto err_request;
  87        }
  88
  89        host->ioaddr = ioremap(iomem->start, resource_size(iomem));
  90        if (!host->ioaddr) {
  91                dev_err(&pdev->dev, "failed to remap registers\n");
  92                ret = -ENOMEM;
  93                goto err_remap;
  94        }
  95
  96        ret = sdhci_add_host(host);
  97        if (ret)
  98                goto err_add_host;
  99
 100        platform_set_drvdata(pdev, host);
 101
 102        return 0;
 103
 104err_add_host:
 105        iounmap(host->ioaddr);
 106err_remap:
 107        release_mem_region(iomem->start, resource_size(iomem));
 108err_request:
 109        sdhci_free_host(host);
 110err:
 111        printk(KERN_ERR"Probing of sdhci-pltfm failed: %d\n", ret);
 112        return ret;
 113}
 114
 115static int __devexit sdhci_pltfm_remove(struct platform_device *pdev)
 116{
 117        struct sdhci_host *host = platform_get_drvdata(pdev);
 118        struct resource *iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 119        int dead;
 120        u32 scratch;
 121
 122        dead = 0;
 123        scratch = readl(host->ioaddr + SDHCI_INT_STATUS);
 124        if (scratch == (u32)-1)
 125                dead = 1;
 126
 127        sdhci_remove_host(host, dead);
 128        iounmap(host->ioaddr);
 129        release_mem_region(iomem->start, resource_size(iomem));
 130        sdhci_free_host(host);
 131        platform_set_drvdata(pdev, NULL);
 132
 133        return 0;
 134}
 135
 136static struct platform_driver sdhci_pltfm_driver = {
 137        .driver = {
 138                .name   = "sdhci",
 139                .owner  = THIS_MODULE,
 140        },
 141        .probe          = sdhci_pltfm_probe,
 142        .remove         = __devexit_p(sdhci_pltfm_remove),
 143};
 144
 145/*****************************************************************************\
 146 *                                                                           *
 147 * Driver init/exit                                                          *
 148 *                                                                           *
 149\*****************************************************************************/
 150
 151static int __init sdhci_drv_init(void)
 152{
 153        return platform_driver_register(&sdhci_pltfm_driver);
 154}
 155
 156static void __exit sdhci_drv_exit(void)
 157{
 158        platform_driver_unregister(&sdhci_pltfm_driver);
 159}
 160
 161module_init(sdhci_drv_init);
 162module_exit(sdhci_drv_exit);
 163
 164MODULE_DESCRIPTION("Secure Digital Host Controller Interface platform driver");
 165MODULE_AUTHOR("Mocean Laboratories <info@mocean-labs.com>");
 166MODULE_LICENSE("GPL v2");
 167MODULE_ALIAS("platform:sdhci");
 168
 169