1 // SPDX-License-Identifier: GPL-2.0-only
3 * drivers/ata/pata_palmld.c
5 * Driver for IDE channel in Palm LifeDrive
7 * Based on research of:
8 * Alex Osborne <ato@meshy.org>
10 * Rewrite for mainline:
11 * Marek Vasut <marek.vasut@gmail.com>
13 * Rewritten version based on pata_ixp4xx_cf.c:
14 * ixp4xx PATA/Compact Flash driver
15 * Copyright (C) 2006-07 Tower Technologies
16 * Author: Alessandro Zummo <a.zummo@towertech.it>
19 #include <linux/kernel.h>
20 #include <linux/module.h>
21 #include <linux/libata.h>
22 #include <linux/irq.h>
23 #include <linux/platform_device.h>
24 #include <linux/delay.h>
25 #include <linux/gpio/consumer.h>
27 #include <scsi/scsi_host.h>
28 #include <mach/palmld.h>
30 #define DRV_NAME "pata_palmld"
33 struct ata_host
*host
;
34 struct gpio_desc
*power
;
35 struct gpio_desc
*reset
;
38 static struct scsi_host_template palmld_sht
= {
39 ATA_PIO_SHT(DRV_NAME
),
42 static struct ata_port_operations palmld_port_ops
= {
43 .inherits
= &ata_sff_port_ops
,
44 .sff_data_xfer
= ata_sff_data_xfer32
,
45 .cable_detect
= ata_cable_40wire
,
48 static int palmld_pata_probe(struct platform_device
*pdev
)
50 struct palmld_pata
*lda
;
53 struct device
*dev
= &pdev
->dev
;
56 lda
= devm_kzalloc(dev
, sizeof(*lda
), GFP_KERNEL
);
61 lda
->host
= ata_host_alloc(dev
, 1);
65 /* remap drive's physical memory address */
66 mem
= devm_ioremap(dev
, PALMLD_IDE_PHYS
, 0x1000);
70 /* request and activate power and reset GPIOs */
71 lda
->power
= devm_gpiod_get(dev
, "power", GPIOD_OUT_HIGH
);
72 if (IS_ERR(lda
->power
))
73 return PTR_ERR(lda
->power
);
74 lda
->reset
= devm_gpiod_get(dev
, "reset", GPIOD_OUT_HIGH
);
75 if (IS_ERR(lda
->reset
)) {
76 gpiod_set_value(lda
->power
, 0);
77 return PTR_ERR(lda
->reset
);
80 /* Assert reset to reset the drive */
81 gpiod_set_value(lda
->reset
, 1);
83 gpiod_set_value(lda
->reset
, 0);
86 /* setup the ata port */
87 ap
= lda
->host
->ports
[0];
88 ap
->ops
= &palmld_port_ops
;
89 ap
->pio_mask
= ATA_PIO4
;
90 ap
->flags
|= ATA_FLAG_PIO_POLLING
;
92 /* memory mapping voodoo */
93 ap
->ioaddr
.cmd_addr
= mem
+ 0x10;
94 ap
->ioaddr
.altstatus_addr
= mem
+ 0xe;
95 ap
->ioaddr
.ctl_addr
= mem
+ 0xe;
98 ata_sff_std_ports(&ap
->ioaddr
);
101 ret
= ata_host_activate(lda
->host
, 0, NULL
, IRQF_TRIGGER_RISING
,
103 /* power down on failure */
105 gpiod_set_value(lda
->power
, 0);
109 platform_set_drvdata(pdev
, lda
);
113 static int palmld_pata_remove(struct platform_device
*pdev
)
115 struct palmld_pata
*lda
= platform_get_drvdata(pdev
);
117 ata_platform_remove_one(pdev
);
119 /* power down the HDD */
120 gpiod_set_value(lda
->power
, 0);
125 static struct platform_driver palmld_pata_platform_driver
= {
129 .probe
= palmld_pata_probe
,
130 .remove
= palmld_pata_remove
,
133 module_platform_driver(palmld_pata_platform_driver
);
135 MODULE_AUTHOR("Marek Vasut <marek.vasut@gmail.com>");
136 MODULE_DESCRIPTION("PalmLD PATA driver");
137 MODULE_LICENSE("GPL");
138 MODULE_ALIAS("platform:" DRV_NAME
);