Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * drivers/ata/pata_palmld.c
0004  *
0005  * Driver for IDE channel in Palm LifeDrive
0006  *
0007  * Based on research of:
0008  *      Alex Osborne <ato@meshy.org>
0009  *
0010  * Rewrite for mainline:
0011  *      Marek Vasut <marek.vasut@gmail.com>
0012  *
0013  * Rewritten version based on pata_ixp4xx_cf.c:
0014  * ixp4xx PATA/Compact Flash driver
0015  * Copyright (C) 2006-07 Tower Technologies
0016  * Author: Alessandro Zummo <a.zummo@towertech.it>
0017  */
0018 
0019 #include <linux/kernel.h>
0020 #include <linux/module.h>
0021 #include <linux/libata.h>
0022 #include <linux/irq.h>
0023 #include <linux/platform_device.h>
0024 #include <linux/delay.h>
0025 #include <linux/gpio/consumer.h>
0026 
0027 #include <scsi/scsi_host.h>
0028 
0029 #define DRV_NAME "pata_palmld"
0030 
0031 struct palmld_pata {
0032     struct ata_host *host;
0033     struct gpio_desc *power;
0034     struct gpio_desc *reset;
0035 };
0036 
0037 static struct scsi_host_template palmld_sht = {
0038     ATA_PIO_SHT(DRV_NAME),
0039 };
0040 
0041 static struct ata_port_operations palmld_port_ops = {
0042     .inherits       = &ata_sff_port_ops,
0043     .sff_data_xfer      = ata_sff_data_xfer32,
0044     .cable_detect       = ata_cable_40wire,
0045 };
0046 
0047 static int palmld_pata_probe(struct platform_device *pdev)
0048 {
0049     struct palmld_pata *lda;
0050     struct ata_port *ap;
0051     void __iomem *mem;
0052     struct device *dev = &pdev->dev;
0053     int ret;
0054 
0055     lda = devm_kzalloc(dev, sizeof(*lda), GFP_KERNEL);
0056     if (!lda)
0057         return -ENOMEM;
0058 
0059     /* allocate host */
0060     lda->host = ata_host_alloc(dev, 1);
0061     if (!lda->host)
0062         return -ENOMEM;
0063 
0064     /* remap drive's physical memory address */
0065     mem = devm_platform_ioremap_resource(pdev, 0);
0066     if (!mem)
0067         return -ENOMEM;
0068 
0069     /* request and activate power and reset GPIOs */
0070     lda->power = devm_gpiod_get(dev, "power", GPIOD_OUT_HIGH);
0071     if (IS_ERR(lda->power))
0072         return PTR_ERR(lda->power);
0073     lda->reset = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH);
0074     if (IS_ERR(lda->reset)) {
0075         gpiod_set_value(lda->power, 0);
0076         return PTR_ERR(lda->reset);
0077     }
0078 
0079     /* Assert reset to reset the drive */
0080     gpiod_set_value(lda->reset, 1);
0081     msleep(30);
0082     gpiod_set_value(lda->reset, 0);
0083     msleep(30);
0084 
0085     /* setup the ata port */
0086     ap = lda->host->ports[0];
0087     ap->ops = &palmld_port_ops;
0088     ap->pio_mask = ATA_PIO4;
0089     ap->flags |= ATA_FLAG_PIO_POLLING;
0090 
0091     /* memory mapping voodoo */
0092     ap->ioaddr.cmd_addr = mem + 0x10;
0093     ap->ioaddr.altstatus_addr = mem + 0xe;
0094     ap->ioaddr.ctl_addr = mem + 0xe;
0095 
0096     /* start the port */
0097     ata_sff_std_ports(&ap->ioaddr);
0098 
0099     /* activate host */
0100     ret = ata_host_activate(lda->host, 0, NULL, IRQF_TRIGGER_RISING,
0101                 &palmld_sht);
0102     /* power down on failure */
0103     if (ret) {
0104         gpiod_set_value(lda->power, 0);
0105         return ret;
0106     }
0107 
0108     platform_set_drvdata(pdev, lda);
0109     return 0;
0110 }
0111 
0112 static int palmld_pata_remove(struct platform_device *pdev)
0113 {
0114     struct palmld_pata *lda = platform_get_drvdata(pdev);
0115 
0116     ata_platform_remove_one(pdev);
0117 
0118     /* power down the HDD */
0119     gpiod_set_value(lda->power, 0);
0120 
0121     return 0;
0122 }
0123 
0124 static struct platform_driver palmld_pata_platform_driver = {
0125     .driver  = {
0126         .name   = DRV_NAME,
0127     },
0128     .probe      = palmld_pata_probe,
0129     .remove     = palmld_pata_remove,
0130 };
0131 
0132 module_platform_driver(palmld_pata_platform_driver);
0133 
0134 MODULE_AUTHOR("Marek Vasut <marek.vasut@gmail.com>");
0135 MODULE_DESCRIPTION("PalmLD PATA driver");
0136 MODULE_LICENSE("GPL");
0137 MODULE_ALIAS("platform:" DRV_NAME);