2 * Support for Gemini PATA
4 * Copyright (C) 2009 Janos Laube <janos.dev@gmail.com>
5 * Copyright (C) 2010 Frederic Pecourt <opengemini@free.fr>
6 * Copyright (C) 2011 Tobias Waldvogel <tobias.waldvogel@gmail.com>
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License along
19 * with this program; if not, write to the Free Software Foundation, Inc.,
20 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
24 * 26:24 bits is "IDE IO Select"
26 * 011 - ata0 <-> sata0, sata1; bring out ata1
27 * 010 - ata1 <-> sata1, sata0; bring out ata0
28 * 001 - ata0 <-> sata0, ata1 <-> sata1; bring out ata1
29 * 000 - ata0 <-> sata0, ata1 <-> sata1; bring out ata0
33 #include <linux/platform_device.h>
34 #include <linux/module.h>
35 #include <linux/moduleparam.h>
36 #include <linux/libata.h>
37 #include <linux/leds.h>
39 #include <mach/hardware.h>
40 #include <mach/global_reg.h>
42 #define DRV_NAME "pata-gemini"
44 #define PATA_GEMINI_PORTS 1
46 #define PIO_TIMING_REG 0x10
47 #define MDMA_TIMING_REG 0x11
48 #define UDMA_TIMING0_REG 0x12
49 #define UDMA_TIMING1_REG 0x13
50 #define CLK_MOD_REG 0x14
52 #define CLK_MOD_66M_DEV0_BIT 0
53 #define CLK_MOD_66M_DEV1_BIT 1
54 #define CLK_MOD_UDMA_DEV0_BIT 4
55 #define CLK_MOD_UDMA_DEV1_BIT 5
57 #define CLK_MOD_66M_DEV0 (1 << CLK_MOD_66M_DEV0_BIT)
58 #define CLK_MOD_66M_DEV1 (1 << CLK_MOD_66M_DEV1_BIT)
59 #define CLK_MOD_UDMA_DEV0 (1 << CLK_MOD_UDMA_DEV0_BIT)
60 #define CLK_MOD_UDMA_DEV1 (1 << CLK_MOD_UDMA_DEV1_BIT)
62 #define SATA_ENABLE_PDEV_MASK 0x01
63 #define SATA_ENABLE_PDEV_PM 0x02
64 #define SATA_ENABLE_PDEV_ADDED 0x04
65 #define SATA_ENABLE_PDEV_REMOVED 0x08
66 #define SATA_ENABLE_SDEV_MASK 0x10
67 #define SATA_ENABLE_SDEV_PM 0x20
68 #define SATA_ENABLE_SDEV_ADDED 0x40
69 #define SATA_ENABLE_SDEV_REMOVED 0x80
71 MODULE_AUTHOR("Janos Laube <janos.dev@gmail.com>");
72 MODULE_LICENSE("GPL");
73 MODULE_ALIAS("platform:" DRV_NAME);
75 static unsigned char PIO_TIMING[5] = {
76 0xaa, 0xa3, 0xa1, 0x33, 0x31
79 static unsigned char TIMING_MW_DMA[4][2] = {
80 { 0x44, 1 }, // 480 4.2
81 { 0x42, 1 }, // 150 13.3
82 { 0x31, 1 }, // 120 16.7
83 { 0x21, 1 }, // 100 20
86 static unsigned char TIMING_UDMA[7][2] = {
87 { 0x33, 0 }, //240 16.7
89 { 0x21, 0 }, //120 33.3
90 { 0x21, 1 }, //90 44.4
91 { 0x11, 1 }, //60 66.7
92 { 0x11 | 0x80, 0 }, //40 100
93 { 0x11 | 0x80, 1 }, //30 133
96 static struct scsi_host_template pata_gemini_sht = {
97 ATA_NCQ_SHT(DRV_NAME),
100 .dma_boundary = 0xffffU,
103 static void gemini_set_dmamode(struct ata_port *ap, struct ata_device *adev)
105 void __iomem *clk_reg = ap->ioaddr.bmdma_addr + CLK_MOD_REG;
106 void __iomem *tim_reg = ap->ioaddr.bmdma_addr + UDMA_TIMING0_REG;
107 unsigned short udma = adev->dma_mode;
108 unsigned short speed = udma;
109 unsigned short devno = adev->devno & 1;
111 u8 mod_udma_mask = 1 << (CLK_MOD_UDMA_DEV0_BIT + devno);
112 u8 mod_66m_mask = 1 << (CLK_MOD_66M_DEV0_BIT + devno);
116 clk_mod = ioread8(clk_reg);
117 clk_mod &= ~mod_udma_mask;
119 if (speed & XFER_UDMA_0) {
120 i = speed & ~XFER_UDMA_0;
121 timing = TIMING_UDMA[i][0];
122 clk_mod |= mod_udma_mask;
123 if (TIMING_UDMA[i][1])
124 clk_mod |= mod_66m_mask;
126 i = speed & ~XFER_MW_DMA_0;
127 timing = TIMING_MW_DMA[i][0];
128 clk_mod |= mod_udma_mask;
129 if (TIMING_MW_DMA[i][1])
130 clk_mod |= mod_66m_mask;
133 iowrite8(clk_mod, clk_reg);
134 iowrite8(timing, tim_reg + devno);
138 static void gemini_set_piomode(struct ata_port *ap, struct ata_device *adev)
140 void __iomem *pio_reg = ap->ioaddr.bmdma_addr + PIO_TIMING_REG;
141 unsigned int pio = adev->pio_mode - XFER_PIO_0;
143 iowrite8(PIO_TIMING[pio], pio_reg);
146 unsigned int gemini_qc_issue(struct ata_queued_cmd *qc)
148 ledtrig_ide_activity();
149 return ata_bmdma_qc_issue(qc);
152 static struct ata_port_operations pata_gemini_port_ops = {
153 .inherits = &ata_bmdma_port_ops,
154 .set_dmamode = gemini_set_dmamode,
155 .set_piomode = gemini_set_piomode,
156 .qc_issue = gemini_qc_issue,
159 static struct ata_port_info pata_gemini_portinfo = {
161 .udma_mask = ATA_UDMA6,
162 .pio_mask = ATA_PIO4,
163 .port_ops = &pata_gemini_port_ops,
166 static const struct ata_port_info *pata_gemini_ports = &pata_gemini_portinfo;
168 static int pata_gemini_probe(struct platform_device *pdev)
170 struct ata_host *host;
171 struct resource *res;
173 void __iomem *mmio_base;
175 /* standard bdma init */
176 irq = platform_get_irq(pdev, 0);
180 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
184 pr_info(DRV_NAME ": irq %d, io base 0x%08x\n", irq, res->start);
186 mmio_base = devm_ioremap(&pdev->dev, res->start, resource_size(res));
188 host = ata_host_alloc_pinfo(&pdev->dev, &pata_gemini_ports, 1);
192 for (i = 0; i < host->n_ports; i++) {
193 struct ata_port *ap = host->ports[i];
194 struct ata_ioports *ioaddr = &ap->ioaddr;
196 ioaddr->bmdma_addr = mmio_base;
197 ioaddr->cmd_addr = mmio_base + 0x20;
198 ioaddr->ctl_addr = mmio_base + 0x36;
199 ioaddr->altstatus_addr = ioaddr->ctl_addr;
200 ata_sff_std_ports(ioaddr);
201 host->ports[i]->cbl = ATA_CBL_SATA;
204 return ata_host_activate(host, irq, ata_bmdma_interrupt,
205 IRQF_SHARED, &pata_gemini_sht);
208 static int pata_gemini_remove(struct platform_device *pdev)
210 struct device *dev = &pdev->dev;
211 struct ata_host *host = dev_get_drvdata(dev);
212 ata_host_detach(host);
216 static struct platform_driver pata_gemini_driver = {
217 .probe = pata_gemini_probe,
218 .remove = pata_gemini_remove,
219 .driver.owner = THIS_MODULE,
220 .driver.name = DRV_NAME,
223 static int __init pata_gemini_module_init(void)
225 return platform_driver_probe(&pata_gemini_driver, pata_gemini_probe);
228 static void __exit pata_gemini_module_exit(void)
230 platform_driver_unregister(&pata_gemini_driver);
233 module_init(pata_gemini_module_init);
234 module_exit(pata_gemini_module_exit);