gemini: add ata driver
[librecmc/librecmc.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);