707e8703bfc9677edb049344551fb63ca4f2bc87
[openwrt/openwrt.git] / target / linux / gemini / files / drivers / ata / pata_gemini.c
1 /*
2 * Support for Gemini PATA
3 *
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>
7 *
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.
12 *
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.
17 *
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.
21 */
22
23 /* Values of IOMUX
24 * 26:24 bits is "IDE IO Select"
25 * 111:100 - Reserved
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
30 *
31 */
32
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>
38
39 #include <mach/hardware.h>
40 #include <mach/global_reg.h>
41
42 #define DRV_NAME "pata-gemini"
43
44 #define PATA_GEMINI_PORTS 1
45
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
51
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
56
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)
61
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
70
71 MODULE_AUTHOR("Janos Laube <janos.dev@gmail.com>");
72 MODULE_LICENSE("GPL");
73 MODULE_ALIAS("platform:" DRV_NAME);
74
75 static unsigned char PIO_TIMING[5] = {
76 0xaa, 0xa3, 0xa1, 0x33, 0x31
77 };
78
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
84 };
85
86 static unsigned char TIMING_UDMA[7][2] = {
87 { 0x33, 0 }, //240 16.7
88 { 0x31, 0 }, //160 25
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
94 };
95
96 static struct scsi_host_template pata_gemini_sht = {
97 ATA_NCQ_SHT(DRV_NAME),
98 .can_queue = 1,
99 .sg_tablesize = 128,
100 .dma_boundary = 0xffffU,
101 };
102
103 static void gemini_set_dmamode(struct ata_port *ap, struct ata_device *adev)
104 {
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;
110 unsigned short i;
111 u8 mod_udma_mask = 1 << (CLK_MOD_UDMA_DEV0_BIT + devno);
112 u8 mod_66m_mask = 1 << (CLK_MOD_66M_DEV0_BIT + devno);
113 u8 clk_mod;
114 u8 timing;
115
116 clk_mod = ioread8(clk_reg);
117 clk_mod &= ~mod_udma_mask;
118
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;
125 } else {
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;
131 }
132
133 iowrite8(clk_mod, clk_reg);
134 iowrite8(timing, tim_reg + devno);
135 return;
136 }
137
138 static void gemini_set_piomode(struct ata_port *ap, struct ata_device *adev)
139 {
140 void __iomem *pio_reg = ap->ioaddr.bmdma_addr + PIO_TIMING_REG;
141 unsigned int pio = adev->pio_mode - XFER_PIO_0;
142
143 iowrite8(PIO_TIMING[pio], pio_reg);
144 }
145
146 unsigned int gemini_qc_issue(struct ata_queued_cmd *qc)
147 {
148 ledtrig_ide_activity();
149 return ata_bmdma_qc_issue(qc);
150 }
151
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,
157 };
158
159 static struct ata_port_info pata_gemini_portinfo = {
160 .flags = 0,
161 .udma_mask = ATA_UDMA6,
162 .pio_mask = ATA_PIO4,
163 .port_ops = &pata_gemini_port_ops,
164 };
165
166 static const struct ata_port_info *pata_gemini_ports = &pata_gemini_portinfo;
167
168 static int pata_gemini_probe(struct platform_device *pdev)
169 {
170 struct ata_host *host;
171 struct resource *res;
172 unsigned int irq, i;
173 void __iomem *mmio_base;
174
175 /* standard bdma init */
176 irq = platform_get_irq(pdev, 0);
177 if (irq < 0)
178 return irq;
179
180 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
181 if (!res)
182 return -ENODEV;
183
184 pr_info(DRV_NAME ": irq %d, io base 0x%08x\n", irq, res->start);
185
186 mmio_base = devm_ioremap(&pdev->dev, res->start, resource_size(res));
187
188 host = ata_host_alloc_pinfo(&pdev->dev, &pata_gemini_ports, 1);
189 if (!host)
190 return -ENOMEM;
191
192 for (i = 0; i < host->n_ports; i++) {
193 struct ata_port *ap = host->ports[i];
194 struct ata_ioports *ioaddr = &ap->ioaddr;
195
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;
202 }
203
204 return ata_host_activate(host, irq, ata_bmdma_interrupt,
205 IRQF_SHARED, &pata_gemini_sht);
206 }
207
208 static int pata_gemini_remove(struct platform_device *pdev)
209 {
210 struct device *dev = &pdev->dev;
211 struct ata_host *host = dev_get_drvdata(dev);
212 ata_host_detach(host);
213 return 0;
214 }
215
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,
221 };
222
223 static int __init pata_gemini_module_init(void)
224 {
225 return platform_driver_probe(&pata_gemini_driver, pata_gemini_probe);
226 }
227
228 static void __exit pata_gemini_module_exit(void)
229 {
230 platform_driver_unregister(&pata_gemini_driver);
231 }
232
233 module_init(pata_gemini_module_init);
234 module_exit(pata_gemini_module_exit);