Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  *  A low-level PATA driver to handle a Compact Flash connected on the
0004  *  Mikrotik's RouterBoard 532 board.
0005  *
0006  *  Copyright (C) 2007 Gabor Juhos <juhosg at openwrt.org>
0007  *  Copyright (C) 2008 Florian Fainelli <florian@openwrt.org>
0008  *
0009  *  This file was based on: drivers/ata/pata_ixp4xx_cf.c
0010  *  Copyright (C) 2006-07 Tower Technologies
0011  *  Author: Alessandro Zummo <a.zummo@towertech.it>
0012  *
0013  *  Also was based on the driver for Linux 2.4.xx published by Mikrotik for
0014  *  their RouterBoard 1xx and 5xx series devices. The original Mikrotik code
0015  *  seems not to have a license.
0016  */
0017 
0018 #include <linux/gfp.h>
0019 #include <linux/kernel.h>
0020 #include <linux/module.h>
0021 #include <linux/platform_device.h>
0022 
0023 #include <linux/io.h>
0024 #include <linux/interrupt.h>
0025 #include <linux/irq.h>
0026 #include <linux/gpio/consumer.h>
0027 
0028 #include <linux/libata.h>
0029 #include <scsi/scsi_host.h>
0030 
0031 #include <asm/mach-rc32434/rb.h>
0032 
0033 #define DRV_NAME    "pata-rb532-cf"
0034 #define DRV_VERSION "0.1.0"
0035 #define DRV_DESC    "PATA driver for RouterBOARD 532 Compact Flash"
0036 
0037 #define RB500_CF_MAXPORTS   1
0038 #define RB500_CF_IO_DELAY   400
0039 
0040 #define RB500_CF_REG_BASE   0x0800
0041 #define RB500_CF_REG_ERR    0x080D
0042 #define RB500_CF_REG_CTRL   0x080E
0043 /* 32bit buffered data register offset */
0044 #define RB500_CF_REG_DBUF32 0x0C00
0045 
0046 struct rb532_cf_info {
0047     void __iomem    *iobase;
0048     struct gpio_desc *gpio_line;
0049     unsigned int    irq;
0050 };
0051 
0052 /* ------------------------------------------------------------------------ */
0053 
0054 static irqreturn_t rb532_pata_irq_handler(int irq, void *dev_instance)
0055 {
0056     struct ata_host *ah = dev_instance;
0057     struct rb532_cf_info *info = ah->private_data;
0058 
0059     if (gpiod_get_value(info->gpio_line)) {
0060         irq_set_irq_type(info->irq, IRQ_TYPE_LEVEL_LOW);
0061         ata_sff_interrupt(info->irq, dev_instance);
0062     } else {
0063         irq_set_irq_type(info->irq, IRQ_TYPE_LEVEL_HIGH);
0064     }
0065 
0066     return IRQ_HANDLED;
0067 }
0068 
0069 static struct ata_port_operations rb532_pata_port_ops = {
0070     .inherits       = &ata_sff_port_ops,
0071     .sff_data_xfer      = ata_sff_data_xfer32,
0072 };
0073 
0074 /* ------------------------------------------------------------------------ */
0075 
0076 static struct scsi_host_template rb532_pata_sht = {
0077     ATA_PIO_SHT(DRV_NAME),
0078 };
0079 
0080 /* ------------------------------------------------------------------------ */
0081 
0082 static void rb532_pata_setup_ports(struct ata_host *ah)
0083 {
0084     struct rb532_cf_info *info = ah->private_data;
0085     struct ata_port *ap;
0086 
0087     ap = ah->ports[0];
0088 
0089     ap->ops     = &rb532_pata_port_ops;
0090     ap->pio_mask    = ATA_PIO4;
0091 
0092     ap->ioaddr.cmd_addr = info->iobase + RB500_CF_REG_BASE;
0093     ap->ioaddr.ctl_addr = info->iobase + RB500_CF_REG_CTRL;
0094     ap->ioaddr.altstatus_addr = info->iobase + RB500_CF_REG_CTRL;
0095 
0096     ata_sff_std_ports(&ap->ioaddr);
0097 
0098     ap->ioaddr.data_addr    = info->iobase + RB500_CF_REG_DBUF32;
0099     ap->ioaddr.error_addr   = info->iobase + RB500_CF_REG_ERR;
0100 }
0101 
0102 static int rb532_pata_driver_probe(struct platform_device *pdev)
0103 {
0104     int irq;
0105     struct gpio_desc *gpiod;
0106     struct resource *res;
0107     struct ata_host *ah;
0108     struct rb532_cf_info *info;
0109     int ret;
0110 
0111     res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
0112     if (!res) {
0113         dev_err(&pdev->dev, "no IOMEM resource found\n");
0114         return -EINVAL;
0115     }
0116 
0117     irq = platform_get_irq(pdev, 0);
0118     if (irq < 0)
0119         return irq;
0120     if (!irq)
0121         return -EINVAL;
0122 
0123     gpiod = devm_gpiod_get(&pdev->dev, NULL, GPIOD_IN);
0124     if (IS_ERR(gpiod)) {
0125         dev_err(&pdev->dev, "no GPIO found for irq%d\n", irq);
0126         return PTR_ERR(gpiod);
0127     }
0128     gpiod_set_consumer_name(gpiod, DRV_NAME);
0129 
0130     /* allocate host */
0131     ah = ata_host_alloc(&pdev->dev, RB500_CF_MAXPORTS);
0132     if (!ah)
0133         return -ENOMEM;
0134 
0135     info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
0136     if (!info)
0137         return -ENOMEM;
0138 
0139     ah->private_data = info;
0140     info->gpio_line = gpiod;
0141     info->irq = irq;
0142 
0143     info->iobase = devm_ioremap(&pdev->dev, res->start,
0144                 resource_size(res));
0145     if (!info->iobase)
0146         return -ENOMEM;
0147 
0148     rb532_pata_setup_ports(ah);
0149 
0150     ret = ata_host_activate(ah, irq, rb532_pata_irq_handler,
0151                 IRQF_TRIGGER_LOW, &rb532_pata_sht);
0152     if (ret)
0153         return ret;
0154 
0155     return 0;
0156 }
0157 
0158 static int rb532_pata_driver_remove(struct platform_device *pdev)
0159 {
0160     struct ata_host *ah = platform_get_drvdata(pdev);
0161 
0162     ata_host_detach(ah);
0163 
0164     return 0;
0165 }
0166 
0167 static struct platform_driver rb532_pata_platform_driver = {
0168     .probe      = rb532_pata_driver_probe,
0169     .remove     = rb532_pata_driver_remove,
0170     .driver  = {
0171         .name   = DRV_NAME,
0172     },
0173 };
0174 
0175 #define DRV_INFO DRV_DESC " version " DRV_VERSION
0176 
0177 module_platform_driver(rb532_pata_platform_driver);
0178 
0179 MODULE_AUTHOR("Gabor Juhos <juhosg at openwrt.org>");
0180 MODULE_AUTHOR("Florian Fainelli <florian@openwrt.org>");
0181 MODULE_DESCRIPTION(DRV_DESC);
0182 MODULE_VERSION(DRV_VERSION);
0183 MODULE_LICENSE("GPL");
0184 MODULE_ALIAS("platform:" DRV_NAME);