linux/drivers/ata/pata_rb532_cf.c
<<
>>
Prefs
   1/*
   2 *  A low-level PATA driver to handle a Compact Flash connected on the
   3 *  Mikrotik's RouterBoard 532 board.
   4 *
   5 *  Copyright (C) 2007 Gabor Juhos <juhosg at openwrt.org>
   6 *  Copyright (C) 2008 Florian Fainelli <florian@openwrt.org>
   7 *
   8 *  This file was based on: drivers/ata/pata_ixp4xx_cf.c
   9 *      Copyright (C) 2006-07 Tower Technologies
  10 *      Author: Alessandro Zummo <a.zummo@towertech.it>
  11 *
  12 *  Also was based on the driver for Linux 2.4.xx published by Mikrotik for
  13 *  their RouterBoard 1xx and 5xx series devices. The original Mikrotik code
  14 *  seems not to have a license.
  15 *
  16 *  This program is free software; you can redistribute it and/or modify
  17 *  it under the terms of the GNU General Public License version 2 as
  18 *  published by the Free Software Foundation.
  19 *
  20 */
  21
  22#include <linux/kernel.h>
  23#include <linux/module.h>
  24#include <linux/platform_device.h>
  25
  26#include <linux/io.h>
  27#include <linux/interrupt.h>
  28#include <linux/irq.h>
  29
  30#include <linux/libata.h>
  31#include <scsi/scsi_host.h>
  32
  33#include <asm/gpio.h>
  34
  35#define DRV_NAME        "pata-rb532-cf"
  36#define DRV_VERSION     "0.1.0"
  37#define DRV_DESC        "PATA driver for RouterBOARD 532 Compact Flash"
  38
  39#define RB500_CF_MAXPORTS       1
  40#define RB500_CF_IO_DELAY       400
  41
  42#define RB500_CF_REG_BASE       0x0800
  43#define RB500_CF_REG_ERR        0x080D
  44#define RB500_CF_REG_CTRL       0x080E
  45/* 32bit buffered data register offset */
  46#define RB500_CF_REG_DBUF32     0x0C00
  47
  48struct rb532_cf_info {
  49        void __iomem    *iobase;
  50        unsigned int    gpio_line;
  51        int             frozen;
  52        unsigned int    irq;
  53};
  54
  55/* ------------------------------------------------------------------------ */
  56
  57static inline void rb532_pata_finish_io(struct ata_port *ap)
  58{
  59        struct ata_host *ah = ap->host;
  60        struct rb532_cf_info *info = ah->private_data;
  61
  62        /* FIXME: Keep previous delay. If this is merely a fence then
  63           ata_sff_sync might be sufficient. */
  64        ata_sff_dma_pause(ap);
  65        ndelay(RB500_CF_IO_DELAY);
  66
  67        set_irq_type(info->irq, IRQ_TYPE_LEVEL_HIGH);
  68}
  69
  70static void rb532_pata_exec_command(struct ata_port *ap,
  71                                const struct ata_taskfile *tf)
  72{
  73        writeb(tf->command, ap->ioaddr.command_addr);
  74        rb532_pata_finish_io(ap);
  75}
  76
  77static unsigned int rb532_pata_data_xfer(struct ata_device *adev, unsigned char *buf,
  78                                unsigned int buflen, int write_data)
  79{
  80        struct ata_port *ap = adev->link->ap;
  81        void __iomem *ioaddr = ap->ioaddr.data_addr;
  82        int retlen = buflen;
  83
  84        if (write_data) {
  85                for (; buflen > 0; buflen--, buf++)
  86                        writeb(*buf, ioaddr);
  87        } else {
  88                for (; buflen > 0; buflen--, buf++)
  89                        *buf = readb(ioaddr);
  90        }
  91
  92        rb532_pata_finish_io(adev->link->ap);
  93        return retlen;
  94}
  95
  96static void rb532_pata_freeze(struct ata_port *ap)
  97{
  98        struct rb532_cf_info *info = ap->host->private_data;
  99
 100        info->frozen = 1;
 101}
 102
 103static void rb532_pata_thaw(struct ata_port *ap)
 104{
 105        struct rb532_cf_info *info = ap->host->private_data;
 106
 107        info->frozen = 0;
 108}
 109
 110static irqreturn_t rb532_pata_irq_handler(int irq, void *dev_instance)
 111{
 112        struct ata_host *ah = dev_instance;
 113        struct rb532_cf_info *info = ah->private_data;
 114
 115        if (gpio_get_value(info->gpio_line)) {
 116                set_irq_type(info->irq, IRQ_TYPE_LEVEL_LOW);
 117                if (!info->frozen)
 118                        ata_sff_interrupt(info->irq, dev_instance);
 119        } else {
 120                set_irq_type(info->irq, IRQ_TYPE_LEVEL_HIGH);
 121        }
 122
 123        return IRQ_HANDLED;
 124}
 125
 126static struct ata_port_operations rb532_pata_port_ops = {
 127        .inherits               = &ata_sff_port_ops,
 128        .sff_exec_command       = rb532_pata_exec_command,
 129        .sff_data_xfer          = rb532_pata_data_xfer,
 130        .freeze                 = rb532_pata_freeze,
 131        .thaw                   = rb532_pata_thaw,
 132};
 133
 134/* ------------------------------------------------------------------------ */
 135
 136static struct scsi_host_template rb532_pata_sht = {
 137        ATA_PIO_SHT(DRV_NAME),
 138};
 139
 140/* ------------------------------------------------------------------------ */
 141
 142static void rb532_pata_setup_ports(struct ata_host *ah)
 143{
 144        struct rb532_cf_info *info = ah->private_data;
 145        struct ata_port *ap;
 146
 147        ap = ah->ports[0];
 148
 149        ap->ops         = &rb532_pata_port_ops;
 150        ap->pio_mask    = 0x1f; /* PIO4 */
 151        ap->flags       = ATA_FLAG_NO_LEGACY | ATA_FLAG_MMIO;
 152
 153        ap->ioaddr.cmd_addr     = info->iobase + RB500_CF_REG_BASE;
 154        ap->ioaddr.ctl_addr     = info->iobase + RB500_CF_REG_CTRL;
 155        ap->ioaddr.altstatus_addr = info->iobase + RB500_CF_REG_CTRL;
 156
 157        ata_sff_std_ports(&ap->ioaddr);
 158
 159        ap->ioaddr.data_addr    = info->iobase + RB500_CF_REG_DBUF32;
 160        ap->ioaddr.error_addr   = info->iobase + RB500_CF_REG_ERR;
 161}
 162
 163static __devinit int rb532_pata_driver_probe(struct platform_device *pdev)
 164{
 165        unsigned int irq;
 166        int gpio;
 167        struct resource *res;
 168        struct ata_host *ah;
 169        struct rb532_cf_info *info;
 170        int ret;
 171
 172        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 173        if (!res) {
 174                dev_err(&pdev->dev, "no IOMEM resource found\n");
 175                return -EINVAL;
 176        }
 177
 178        irq = platform_get_irq(pdev, 0);
 179        if (irq <= 0) {
 180                dev_err(&pdev->dev, "no IRQ resource found\n");
 181                return -ENOENT;
 182        }
 183
 184        gpio = irq_to_gpio(irq);
 185        if (gpio < 0) {
 186                dev_err(&pdev->dev, "no GPIO found for irq%d\n", irq);
 187                return -ENOENT;
 188        }
 189
 190        ret = gpio_request(gpio, DRV_NAME);
 191        if (ret) {
 192                dev_err(&pdev->dev, "GPIO request failed\n");
 193                return ret;
 194        }
 195
 196        /* allocate host */
 197        ah = ata_host_alloc(&pdev->dev, RB500_CF_MAXPORTS);
 198        if (!ah)
 199                return -ENOMEM;
 200
 201        platform_set_drvdata(pdev, ah);
 202
 203        info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
 204        if (!info)
 205                return -ENOMEM;
 206
 207        ah->private_data = info;
 208        info->gpio_line = gpio;
 209        info->irq = irq;
 210
 211        info->iobase = devm_ioremap_nocache(&pdev->dev, res->start,
 212                                res->end - res->start + 1);
 213        if (!info->iobase)
 214                return -ENOMEM;
 215
 216        ret = gpio_direction_input(gpio);
 217        if (ret) {
 218                dev_err(&pdev->dev, "unable to set GPIO direction, err=%d\n",
 219                                ret);
 220                goto err_free_gpio;
 221        }
 222
 223        rb532_pata_setup_ports(ah);
 224
 225        ret = ata_host_activate(ah, irq, rb532_pata_irq_handler,
 226                                IRQF_TRIGGER_LOW, &rb532_pata_sht);
 227        if (ret)
 228                goto err_free_gpio;
 229
 230        return 0;
 231
 232err_free_gpio:
 233        gpio_free(gpio);
 234
 235        return ret;
 236}
 237
 238static __devexit int rb532_pata_driver_remove(struct platform_device *pdev)
 239{
 240        struct ata_host *ah = platform_get_drvdata(pdev);
 241        struct rb532_cf_info *info = ah->private_data;
 242
 243        ata_host_detach(ah);
 244        gpio_free(info->gpio_line);
 245
 246        return 0;
 247}
 248
 249/* work with hotplug and coldplug */
 250MODULE_ALIAS("platform:" DRV_NAME);
 251
 252static struct platform_driver rb532_pata_platform_driver = {
 253        .probe          = rb532_pata_driver_probe,
 254        .remove         = __devexit_p(rb532_pata_driver_remove),
 255        .driver  = {
 256                .name   = DRV_NAME,
 257                .owner  = THIS_MODULE,
 258        },
 259};
 260
 261/* ------------------------------------------------------------------------ */
 262
 263#define DRV_INFO DRV_DESC " version " DRV_VERSION
 264
 265static int __init rb532_pata_module_init(void)
 266{
 267        printk(KERN_INFO DRV_INFO "\n");
 268
 269        return platform_driver_register(&rb532_pata_platform_driver);
 270}
 271
 272static void __exit rb532_pata_module_exit(void)
 273{
 274        platform_driver_unregister(&rb532_pata_platform_driver);
 275}
 276
 277MODULE_AUTHOR("Gabor Juhos <juhosg at openwrt.org>");
 278MODULE_AUTHOR("Florian Fainelli <florian@openwrt.org>");
 279MODULE_DESCRIPTION(DRV_DESC);
 280MODULE_VERSION(DRV_VERSION);
 281MODULE_LICENSE("GPL");
 282
 283module_init(rb532_pata_module_init);
 284module_exit(rb532_pata_module_exit);
 285