linux/drivers/ata/pata_palmld.c
<<
>>
Prefs
   1/*
   2 * drivers/ata/pata_palmld.c
   3 *
   4 * Driver for IDE channel in Palm LifeDrive
   5 *
   6 * Based on research of:
   7 *              Alex Osborne <ato@meshy.org>
   8 *
   9 * Rewrite for mainline:
  10 *              Marek Vasut <marek.vasut@gmail.com>
  11 *
  12 * Rewritten version based on pata_ixp4xx_cf.c:
  13 * ixp4xx PATA/Compact Flash driver
  14 * Copyright (C) 2006-07 Tower Technologies
  15 * Author: Alessandro Zummo <a.zummo@towertech.it>
  16 *
  17 * This program is free software; you can redistribute it and/or modify
  18 * it under the terms of the GNU General Public License version 2 as
  19 * published by the Free Software Foundation.
  20 *
  21 */
  22
  23#include <linux/kernel.h>
  24#include <linux/module.h>
  25#include <linux/libata.h>
  26#include <linux/irq.h>
  27#include <linux/platform_device.h>
  28#include <linux/delay.h>
  29#include <linux/gpio.h>
  30
  31#include <scsi/scsi_host.h>
  32#include <mach/palmld.h>
  33
  34#define DRV_NAME "pata_palmld"
  35
  36static struct scsi_host_template palmld_sht = {
  37        ATA_PIO_SHT(DRV_NAME),
  38};
  39
  40static struct ata_port_operations palmld_port_ops = {
  41        .inherits               = &ata_sff_port_ops,
  42        .sff_data_xfer          = ata_sff_data_xfer_noirq,
  43        .cable_detect           = ata_cable_40wire,
  44};
  45
  46static __devinit int palmld_pata_probe(struct platform_device *pdev)
  47{
  48        struct ata_host *host;
  49        struct ata_port *ap;
  50        void __iomem *mem;
  51        int ret;
  52
  53        /* allocate host */
  54        host = ata_host_alloc(&pdev->dev, 1);
  55        if (!host)
  56                return -ENOMEM;
  57
  58        /* remap drive's physical memory address */
  59        mem = devm_ioremap(&pdev->dev, PALMLD_IDE_PHYS, 0x1000);
  60        if (!mem)
  61                return -ENOMEM;
  62
  63        /* request and activate power GPIO, IRQ GPIO */
  64        ret = gpio_request(GPIO_NR_PALMLD_IDE_PWEN, "HDD PWR");
  65        if (ret)
  66                goto err1;
  67        ret = gpio_direction_output(GPIO_NR_PALMLD_IDE_PWEN, 1);
  68        if (ret)
  69                goto err2;
  70
  71        ret = gpio_request(GPIO_NR_PALMLD_IDE_RESET, "HDD RST");
  72        if (ret)
  73                goto err2;
  74        ret = gpio_direction_output(GPIO_NR_PALMLD_IDE_RESET, 0);
  75        if (ret)
  76                goto err3;
  77
  78        /* reset the drive */
  79        gpio_set_value(GPIO_NR_PALMLD_IDE_RESET, 0);
  80        msleep(30);
  81        gpio_set_value(GPIO_NR_PALMLD_IDE_RESET, 1);
  82        msleep(30);
  83
  84        /* setup the ata port */
  85        ap = host->ports[0];
  86        ap->ops = &palmld_port_ops;
  87        ap->pio_mask = ATA_PIO4;
  88        ap->flags |= ATA_FLAG_MMIO | ATA_FLAG_NO_LEGACY | ATA_FLAG_PIO_POLLING;
  89
  90        /* memory mapping voodoo */
  91        ap->ioaddr.cmd_addr = mem + 0x10;
  92        ap->ioaddr.altstatus_addr = mem + 0xe;
  93        ap->ioaddr.ctl_addr = mem + 0xe;
  94
  95        /* start the port */
  96        ata_sff_std_ports(&ap->ioaddr);
  97
  98        /* activate host */
  99        return ata_host_activate(host, 0, NULL, IRQF_TRIGGER_RISING,
 100                                        &palmld_sht);
 101
 102err3:
 103        gpio_free(GPIO_NR_PALMLD_IDE_RESET);
 104err2:
 105        gpio_free(GPIO_NR_PALMLD_IDE_PWEN);
 106err1:
 107        return ret;
 108}
 109
 110static __devexit int palmld_pata_remove(struct platform_device *dev)
 111{
 112        struct ata_host *host = platform_get_drvdata(dev);
 113
 114        ata_host_detach(host);
 115
 116        /* power down the HDD */
 117        gpio_set_value(GPIO_NR_PALMLD_IDE_PWEN, 0);
 118
 119        gpio_free(GPIO_NR_PALMLD_IDE_RESET);
 120        gpio_free(GPIO_NR_PALMLD_IDE_PWEN);
 121
 122        return 0;
 123}
 124
 125static struct platform_driver palmld_pata_platform_driver = {
 126        .driver  = {
 127                .name   = DRV_NAME,
 128                .owner  = THIS_MODULE,
 129        },
 130        .probe          = palmld_pata_probe,
 131        .remove         = __devexit_p(palmld_pata_remove),
 132};
 133
 134static int __init palmld_pata_init(void)
 135{
 136        return platform_driver_register(&palmld_pata_platform_driver);
 137}
 138
 139static void __exit palmld_pata_exit(void)
 140{
 141        platform_driver_unregister(&palmld_pata_platform_driver);
 142}
 143
 144MODULE_AUTHOR("Marek Vasut <marek.vasut@gmail.com>");
 145MODULE_DESCRIPTION("PalmLD PATA driver");
 146MODULE_LICENSE("GPL");
 147MODULE_ALIAS("platform:" DRV_NAME);
 148
 149module_init(palmld_pata_init);
 150module_exit(palmld_pata_exit);
 151