Commit 7c7e92a9268965e08bba853ecdb94fa55e886741
Committed by
Bartlomiej Zolnierkiewicz
1 parent
b2a53bc636
Exists in
master
and in
7 other branches
Palmchip BK3710 IDE driver
This is Palmchip BK3710 IDE controller support. The IDE controller logic supports PIO, MultiWord-DMA and Ultra-DMA modes. Supports interface to Compact Flash (CF) configured in True-IDE mode. Bart: - remove dead code - fix ide_hwif_setup_dma() build problem Signed-off-by: Anton Salnikov <asalnikov@ru.mvista.com> Reviewed-by: Alan Cox <alan@lxorguk.ukuu.org.uk> Reviewed-by: Sergei Shtylyov <sshtylyov@ru.mvista.com> Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
Showing 5 changed files with 409 additions and 2 deletions Side-by-side Diff
drivers/ide/Kconfig
... | ... | @@ -1009,6 +1009,15 @@ |
1009 | 1009 | normally be on; disable it only if you are running a custom hard |
1010 | 1010 | drive subsystem through an expansion card. |
1011 | 1011 | |
1012 | +config BLK_DEV_PALMCHIP_BK3710 | |
1013 | + tristate "Palmchip bk3710 IDE controller support" | |
1014 | + depends on ARCH_DAVINCI | |
1015 | + select BLK_DEV_IDEDMA_PCI | |
1016 | + help | |
1017 | + Say Y here if you want to support the onchip IDE controller on the | |
1018 | + TI DaVinci SoC | |
1019 | + | |
1020 | + | |
1012 | 1021 | config BLK_DEV_MPC8xx_IDE |
1013 | 1022 | tristate "MPC8xx IDE support" |
1014 | 1023 | depends on 8xx && (LWMON || IVMS8 || IVML24 || TQM8xxL) && IDE=y && BLK_DEV_IDE=y && !PPC_MERGE |
drivers/ide/arm/Makefile
drivers/ide/arm/palm_bk3710.c
1 | +/* | |
2 | + * Palmchip bk3710 IDE controller | |
3 | + * | |
4 | + * Copyright (C) 2006 Texas Instruments. | |
5 | + * Copyright (C) 2007 MontaVista Software, Inc., <source@mvista.com> | |
6 | + * | |
7 | + * ---------------------------------------------------------------------------- | |
8 | + * | |
9 | + * This program is free software; you can redistribute it and/or modify | |
10 | + * it under the terms of the GNU General Public License as published by | |
11 | + * the Free Software Foundation; either version 2 of the License, or | |
12 | + * (at your option) any later version. | |
13 | + * | |
14 | + * This program is distributed in the hope that it will be useful, | |
15 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
16 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
17 | + * GNU General Public License for more details. | |
18 | + * | |
19 | + * You should have received a copy of the GNU General Public License | |
20 | + * along with this program; if not, write to the Free Software | |
21 | + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |
22 | + * ---------------------------------------------------------------------------- | |
23 | + * | |
24 | + */ | |
25 | + | |
26 | +#include <linux/types.h> | |
27 | +#include <linux/module.h> | |
28 | +#include <linux/kernel.h> | |
29 | +#include <linux/ioport.h> | |
30 | +#include <linux/hdreg.h> | |
31 | +#include <linux/ide.h> | |
32 | +#include <linux/delay.h> | |
33 | +#include <linux/init.h> | |
34 | +#include <linux/clk.h> | |
35 | +#include <linux/platform_device.h> | |
36 | + | |
37 | +/* Offset of the primary interface registers */ | |
38 | +#define IDE_PALM_ATA_PRI_REG_OFFSET 0x1F0 | |
39 | + | |
40 | +/* Primary Control Offset */ | |
41 | +#define IDE_PALM_ATA_PRI_CTL_OFFSET 0x3F6 | |
42 | + | |
43 | +/* | |
44 | + * PalmChip 3710 IDE Controller UDMA timing structure Definition | |
45 | + */ | |
46 | +struct palm_bk3710_udmatiming { | |
47 | + unsigned int rptime; /* Ready to pause time */ | |
48 | + unsigned int cycletime; /* Cycle Time */ | |
49 | +}; | |
50 | + | |
51 | +#define BK3710_BMICP 0x00 | |
52 | +#define BK3710_BMISP 0x02 | |
53 | +#define BK3710_BMIDTP 0x04 | |
54 | +#define BK3710_BMICS 0x08 | |
55 | +#define BK3710_BMISS 0x0A | |
56 | +#define BK3710_BMIDTS 0x0C | |
57 | +#define BK3710_IDETIMP 0x40 | |
58 | +#define BK3710_IDETIMS 0x42 | |
59 | +#define BK3710_SIDETIM 0x44 | |
60 | +#define BK3710_SLEWCTL 0x45 | |
61 | +#define BK3710_IDESTATUS 0x47 | |
62 | +#define BK3710_UDMACTL 0x48 | |
63 | +#define BK3710_UDMATIM 0x4A | |
64 | +#define BK3710_MISCCTL 0x50 | |
65 | +#define BK3710_REGSTB 0x54 | |
66 | +#define BK3710_REGRCVR 0x58 | |
67 | +#define BK3710_DATSTB 0x5C | |
68 | +#define BK3710_DATRCVR 0x60 | |
69 | +#define BK3710_DMASTB 0x64 | |
70 | +#define BK3710_DMARCVR 0x68 | |
71 | +#define BK3710_UDMASTB 0x6C | |
72 | +#define BK3710_UDMATRP 0x70 | |
73 | +#define BK3710_UDMAENV 0x74 | |
74 | +#define BK3710_IORDYTMP 0x78 | |
75 | +#define BK3710_IORDYTMS 0x7C | |
76 | + | |
77 | +#include "../ide-timing.h" | |
78 | + | |
79 | +static long ide_palm_clk; | |
80 | + | |
81 | +static const struct palm_bk3710_udmatiming palm_bk3710_udmatimings[6] = { | |
82 | + {160, 240}, /* UDMA Mode 0 */ | |
83 | + {125, 160}, /* UDMA Mode 1 */ | |
84 | + {100, 120}, /* UDMA Mode 2 */ | |
85 | + {100, 90}, /* UDMA Mode 3 */ | |
86 | + {85, 60}, /* UDMA Mode 4 */ | |
87 | +}; | |
88 | + | |
89 | +static struct clk *ideclkp; | |
90 | + | |
91 | +static void palm_bk3710_setudmamode(void __iomem *base, unsigned int dev, | |
92 | + unsigned int mode) | |
93 | +{ | |
94 | + u8 tenv, trp, t0; | |
95 | + u32 val32; | |
96 | + u16 val16; | |
97 | + | |
98 | + /* DMA Data Setup */ | |
99 | + t0 = (palm_bk3710_udmatimings[mode].cycletime + ide_palm_clk - 1) | |
100 | + / ide_palm_clk - 1; | |
101 | + tenv = (20 + ide_palm_clk - 1) / ide_palm_clk - 1; | |
102 | + trp = (palm_bk3710_udmatimings[mode].rptime + ide_palm_clk - 1) | |
103 | + / ide_palm_clk - 1; | |
104 | + | |
105 | + /* udmatim Register */ | |
106 | + val16 = readw(base + BK3710_UDMATIM) & (dev ? 0xFF0F : 0xFFF0); | |
107 | + val16 |= (mode << (dev ? 4 : 0)); | |
108 | + writew(val16, base + BK3710_UDMATIM); | |
109 | + | |
110 | + /* udmastb Ultra DMA Access Strobe Width */ | |
111 | + val32 = readl(base + BK3710_UDMASTB) & (0xFF << (dev ? 0 : 8)); | |
112 | + val32 |= (t0 << (dev ? 8 : 0)); | |
113 | + writel(val32, base + BK3710_UDMASTB); | |
114 | + | |
115 | + /* udmatrp Ultra DMA Ready to Pause Time */ | |
116 | + val32 = readl(base + BK3710_UDMATRP) & (0xFF << (dev ? 0 : 8)); | |
117 | + val32 |= (trp << (dev ? 8 : 0)); | |
118 | + writel(val32, base + BK3710_UDMATRP); | |
119 | + | |
120 | + /* udmaenv Ultra DMA envelop Time */ | |
121 | + val32 = readl(base + BK3710_UDMAENV) & (0xFF << (dev ? 0 : 8)); | |
122 | + val32 |= (tenv << (dev ? 8 : 0)); | |
123 | + writel(val32, base + BK3710_UDMAENV); | |
124 | + | |
125 | + /* Enable UDMA for Device */ | |
126 | + val16 = readw(base + BK3710_UDMACTL) | (1 << dev); | |
127 | + writew(val16, base + BK3710_UDMACTL); | |
128 | +} | |
129 | + | |
130 | +static void palm_bk3710_setdmamode(void __iomem *base, unsigned int dev, | |
131 | + unsigned short min_cycle, | |
132 | + unsigned int mode) | |
133 | +{ | |
134 | + u8 td, tkw, t0; | |
135 | + u32 val32; | |
136 | + u16 val16; | |
137 | + struct ide_timing *t; | |
138 | + int cycletime; | |
139 | + | |
140 | + t = ide_timing_find_mode(mode); | |
141 | + cycletime = max_t(int, t->cycle, min_cycle); | |
142 | + | |
143 | + /* DMA Data Setup */ | |
144 | + t0 = (cycletime + ide_palm_clk - 1) / ide_palm_clk; | |
145 | + td = (t->active + ide_palm_clk - 1) / ide_palm_clk; | |
146 | + tkw = t0 - td - 1; | |
147 | + td -= 1; | |
148 | + | |
149 | + val32 = readl(base + BK3710_DMASTB) & (0xFF << (dev ? 0 : 8)); | |
150 | + val32 |= (td << (dev ? 8 : 0)); | |
151 | + writel(val32, base + BK3710_DMASTB); | |
152 | + | |
153 | + val32 = readl(base + BK3710_DMARCVR) & (0xFF << (dev ? 0 : 8)); | |
154 | + val32 |= (tkw << (dev ? 8 : 0)); | |
155 | + writel(val32, base + BK3710_DMARCVR); | |
156 | + | |
157 | + /* Disable UDMA for Device */ | |
158 | + val16 = readw(base + BK3710_UDMACTL) & ~(1 << dev); | |
159 | + writew(val16, base + BK3710_UDMACTL); | |
160 | +} | |
161 | + | |
162 | +static void palm_bk3710_setpiomode(void __iomem *base, ide_drive_t *mate, | |
163 | + unsigned int dev, unsigned int cycletime, | |
164 | + unsigned int mode) | |
165 | +{ | |
166 | + u8 t2, t2i, t0; | |
167 | + u32 val32; | |
168 | + struct ide_timing *t; | |
169 | + | |
170 | + /* PIO Data Setup */ | |
171 | + t0 = (cycletime + ide_palm_clk - 1) / ide_palm_clk; | |
172 | + t2 = (ide_timing_find_mode(XFER_PIO_0 + mode)->active + | |
173 | + ide_palm_clk - 1) / ide_palm_clk; | |
174 | + | |
175 | + t2i = t0 - t2 - 1; | |
176 | + t2 -= 1; | |
177 | + | |
178 | + val32 = readl(base + BK3710_DATSTB) & (0xFF << (dev ? 0 : 8)); | |
179 | + val32 |= (t2 << (dev ? 8 : 0)); | |
180 | + writel(val32, base + BK3710_DATSTB); | |
181 | + | |
182 | + val32 = readl(base + BK3710_DATRCVR) & (0xFF << (dev ? 0 : 8)); | |
183 | + val32 |= (t2i << (dev ? 8 : 0)); | |
184 | + writel(val32, base + BK3710_DATRCVR); | |
185 | + | |
186 | + if (mate && mate->present) { | |
187 | + u8 mode2 = ide_get_best_pio_mode(mate, 255, 4); | |
188 | + | |
189 | + if (mode2 < mode) | |
190 | + mode = mode2; | |
191 | + } | |
192 | + | |
193 | + /* TASKFILE Setup */ | |
194 | + t = ide_timing_find_mode(XFER_PIO_0 + mode); | |
195 | + t0 = (t->cyc8b + ide_palm_clk - 1) / ide_palm_clk; | |
196 | + t2 = (t->act8b + ide_palm_clk - 1) / ide_palm_clk; | |
197 | + | |
198 | + t2i = t0 - t2 - 1; | |
199 | + t2 -= 1; | |
200 | + | |
201 | + val32 = readl(base + BK3710_REGSTB) & (0xFF << (dev ? 0 : 8)); | |
202 | + val32 |= (t2 << (dev ? 8 : 0)); | |
203 | + writel(val32, base + BK3710_REGSTB); | |
204 | + | |
205 | + val32 = readl(base + BK3710_REGRCVR) & (0xFF << (dev ? 0 : 8)); | |
206 | + val32 |= (t2i << (dev ? 8 : 0)); | |
207 | + writel(val32, base + BK3710_REGRCVR); | |
208 | +} | |
209 | + | |
210 | +static void palm_bk3710_set_dma_mode(ide_drive_t *drive, u8 xferspeed) | |
211 | +{ | |
212 | + int is_slave = drive->dn & 1; | |
213 | + void __iomem *base = (void *)drive->hwif->dma_base; | |
214 | + | |
215 | + if (xferspeed >= XFER_UDMA_0) { | |
216 | + palm_bk3710_setudmamode(base, is_slave, | |
217 | + xferspeed - XFER_UDMA_0); | |
218 | + } else { | |
219 | + palm_bk3710_setdmamode(base, is_slave, drive->id->eide_dma_min, | |
220 | + xferspeed); | |
221 | + } | |
222 | +} | |
223 | + | |
224 | +static void palm_bk3710_set_pio_mode(ide_drive_t *drive, u8 pio) | |
225 | +{ | |
226 | + unsigned int cycle_time; | |
227 | + int is_slave = drive->dn & 1; | |
228 | + ide_drive_t *mate; | |
229 | + void __iomem *base = (void *)drive->hwif->dma_base; | |
230 | + | |
231 | + /* | |
232 | + * Obtain the drive PIO data for tuning the Palm Chip registers | |
233 | + */ | |
234 | + cycle_time = ide_pio_cycle_time(drive, pio); | |
235 | + mate = ide_get_paired_drive(drive); | |
236 | + palm_bk3710_setpiomode(base, mate, is_slave, cycle_time, pio); | |
237 | +} | |
238 | + | |
239 | +static void __devinit palm_bk3710_chipinit(void __iomem *base) | |
240 | +{ | |
241 | + /* | |
242 | + * enable the reset_en of ATA controller so that when ata signals | |
243 | + * are brought out, by writing into device config. at that | |
244 | + * time por_n signal should not be 'Z' and have a stable value. | |
245 | + */ | |
246 | + writel(0x0300, base + BK3710_MISCCTL); | |
247 | + | |
248 | + /* wait for some time and deassert the reset of ATA Device. */ | |
249 | + mdelay(100); | |
250 | + | |
251 | + /* Deassert the Reset */ | |
252 | + writel(0x0200, base + BK3710_MISCCTL); | |
253 | + | |
254 | + /* | |
255 | + * Program the IDETIMP Register Value based on the following assumptions | |
256 | + * | |
257 | + * (ATA_IDETIMP_IDEEN , ENABLE ) | | |
258 | + * (ATA_IDETIMP_SLVTIMEN , DISABLE) | | |
259 | + * (ATA_IDETIMP_RDYSMPL , 70NS) | | |
260 | + * (ATA_IDETIMP_RDYRCVRY , 50NS) | | |
261 | + * (ATA_IDETIMP_DMAFTIM1 , PIOCOMP) | | |
262 | + * (ATA_IDETIMP_PREPOST1 , DISABLE) | | |
263 | + * (ATA_IDETIMP_RDYSEN1 , DISABLE) | | |
264 | + * (ATA_IDETIMP_PIOFTIM1 , DISABLE) | | |
265 | + * (ATA_IDETIMP_DMAFTIM0 , PIOCOMP) | | |
266 | + * (ATA_IDETIMP_PREPOST0 , DISABLE) | | |
267 | + * (ATA_IDETIMP_RDYSEN0 , DISABLE) | | |
268 | + * (ATA_IDETIMP_PIOFTIM0 , DISABLE) | |
269 | + */ | |
270 | + writew(0xB388, base + BK3710_IDETIMP); | |
271 | + | |
272 | + /* | |
273 | + * Configure SIDETIM Register | |
274 | + * (ATA_SIDETIM_RDYSMPS1 ,120NS ) | | |
275 | + * (ATA_SIDETIM_RDYRCYS1 ,120NS ) | |
276 | + */ | |
277 | + writeb(0, base + BK3710_SIDETIM); | |
278 | + | |
279 | + /* | |
280 | + * UDMACTL Ultra-ATA DMA Control | |
281 | + * (ATA_UDMACTL_UDMAP1 , 0 ) | | |
282 | + * (ATA_UDMACTL_UDMAP0 , 0 ) | |
283 | + * | |
284 | + */ | |
285 | + writew(0, base + BK3710_UDMACTL); | |
286 | + | |
287 | + /* | |
288 | + * MISCCTL Miscellaneous Conrol Register | |
289 | + * (ATA_MISCCTL_RSTMODEP , 1) | | |
290 | + * (ATA_MISCCTL_RESETP , 0) | | |
291 | + * (ATA_MISCCTL_TIMORIDE , 1) | |
292 | + */ | |
293 | + writel(0x201, base + BK3710_MISCCTL); | |
294 | + | |
295 | + /* | |
296 | + * IORDYTMP IORDY Timer for Primary Register | |
297 | + * (ATA_IORDYTMP_IORDYTMP , 0xffff ) | |
298 | + */ | |
299 | + writel(0xFFFF, base + BK3710_IORDYTMP); | |
300 | + | |
301 | + /* | |
302 | + * Configure BMISP Register | |
303 | + * (ATA_BMISP_DMAEN1 , DISABLE ) | | |
304 | + * (ATA_BMISP_DMAEN0 , DISABLE ) | | |
305 | + * (ATA_BMISP_IORDYINT , CLEAR) | | |
306 | + * (ATA_BMISP_INTRSTAT , CLEAR) | | |
307 | + * (ATA_BMISP_DMAERROR , CLEAR) | |
308 | + */ | |
309 | + writew(0, base + BK3710_BMISP); | |
310 | + | |
311 | + palm_bk3710_setpiomode(base, NULL, 0, 600, 0); | |
312 | + palm_bk3710_setpiomode(base, NULL, 1, 600, 0); | |
313 | +} | |
314 | +static int __devinit palm_bk3710_probe(struct platform_device *pdev) | |
315 | +{ | |
316 | + hw_regs_t ide_ctlr_info; | |
317 | + int index = 0; | |
318 | + int pribase; | |
319 | + struct clk *clkp; | |
320 | + struct resource *mem, *irq; | |
321 | + ide_hwif_t *hwif; | |
322 | + void __iomem *base; | |
323 | + | |
324 | + clkp = clk_get(NULL, "IDECLK"); | |
325 | + if (IS_ERR(clkp)) | |
326 | + return -ENODEV; | |
327 | + | |
328 | + ideclkp = clkp; | |
329 | + clk_enable(ideclkp); | |
330 | + ide_palm_clk = clk_get_rate(ideclkp)/100000; | |
331 | + ide_palm_clk = (10000/ide_palm_clk) + 1; | |
332 | + /* Register the IDE interface with Linux ATA Interface */ | |
333 | + memset(&ide_ctlr_info, 0, sizeof(ide_ctlr_info)); | |
334 | + | |
335 | + mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); | |
336 | + if (mem == NULL) { | |
337 | + printk(KERN_ERR "failed to get memory region resource\n"); | |
338 | + return -ENODEV; | |
339 | + } | |
340 | + irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0); | |
341 | + if (irq == NULL) { | |
342 | + printk(KERN_ERR "failed to get IRQ resource\n"); | |
343 | + return -ENODEV; | |
344 | + } | |
345 | + | |
346 | + base = (void *)mem->start; | |
347 | + | |
348 | + /* Configure the Palm Chip controller */ | |
349 | + palm_bk3710_chipinit(base); | |
350 | + | |
351 | + pribase = mem->start + IDE_PALM_ATA_PRI_REG_OFFSET; | |
352 | + for (index = 0; index < IDE_NR_PORTS - 2; index++) | |
353 | + ide_ctlr_info.io_ports[index] = pribase + index; | |
354 | + ide_ctlr_info.io_ports[IDE_CONTROL_OFFSET] = mem->start + | |
355 | + IDE_PALM_ATA_PRI_CTL_OFFSET; | |
356 | + ide_ctlr_info.irq = irq->start; | |
357 | + ide_ctlr_info.chipset = ide_palm3710; | |
358 | + | |
359 | + if (ide_register_hw(&ide_ctlr_info, NULL, &hwif) < 0) { | |
360 | + printk(KERN_WARNING "Palm Chip BK3710 IDE Register Fail\n"); | |
361 | + return -ENODEV; | |
362 | + } | |
363 | + | |
364 | + hwif->set_pio_mode = &palm_bk3710_set_pio_mode; | |
365 | + hwif->set_dma_mode = &palm_bk3710_set_dma_mode; | |
366 | + hwif->mmio = 1; | |
367 | + default_hwif_mmiops(hwif); | |
368 | + hwif->cbl = ATA_CBL_PATA80; | |
369 | + hwif->ultra_mask = 0x1f; /* Ultra DMA Mode 4 Max | |
370 | + (input clk 99MHz) */ | |
371 | + hwif->mwdma_mask = 0x7; | |
372 | + hwif->drives[0].autotune = 1; | |
373 | + hwif->drives[1].autotune = 1; | |
374 | + | |
375 | + ide_setup_dma(hwif, mem->start); | |
376 | + | |
377 | + return 0; | |
378 | +} | |
379 | + | |
380 | +static struct platform_driver platform_bk_driver = { | |
381 | + .driver = { | |
382 | + .name = "palm_bk3710", | |
383 | + }, | |
384 | + .probe = palm_bk3710_probe, | |
385 | + .remove = NULL, | |
386 | +}; | |
387 | + | |
388 | +static int __init palm_bk3710_init(void) | |
389 | +{ | |
390 | + return platform_driver_register(&platform_bk_driver); | |
391 | +} | |
392 | + | |
393 | +module_init(palm_bk3710_init); | |
394 | +MODULE_LICENSE("GPL"); |
drivers/ide/ide-proc.c
... | ... | @@ -65,6 +65,7 @@ |
65 | 65 | case ide_4drives: name = "4drives"; break; |
66 | 66 | case ide_pmac: name = "mac-io"; break; |
67 | 67 | case ide_au1xxx: name = "au1xxx"; break; |
68 | + case ide_palm3710: name = "palm3710"; break; | |
68 | 69 | case ide_etrax100: name = "etrax100"; break; |
69 | 70 | case ide_acorn: name = "acorn"; break; |
70 | 71 | default: name = "(unknown)"; break; |
include/linux/ide.h
... | ... | @@ -173,7 +173,7 @@ |
173 | 173 | ide_rz1000, ide_trm290, |
174 | 174 | ide_cmd646, ide_cy82c693, ide_4drives, |
175 | 175 | ide_pmac, ide_etrax100, ide_acorn, |
176 | - ide_au1xxx, ide_forced | |
176 | + ide_au1xxx, ide_palm3710, ide_forced | |
177 | 177 | }; |
178 | 178 | |
179 | 179 | typedef u8 hwif_chipset_t; |
... | ... | @@ -1014,7 +1014,8 @@ |
1014 | 1014 | void ide_pci_setup_ports(struct pci_dev *, const struct ide_port_info *, int, u8 *); |
1015 | 1015 | void ide_setup_pci_noise(struct pci_dev *, const struct ide_port_info *); |
1016 | 1016 | |
1017 | -#ifdef CONFIG_BLK_DEV_IDEDMA_PCI | |
1017 | +/* FIXME: palm_bk3710 uses BLK_DEV_IDEDMA_PCI without BLK_DEV_IDEPCI! */ | |
1018 | +#if defined(CONFIG_BLK_DEV_IDEPCI) && defined(CONFIG_BLK_DEV_IDEDMA_PCI) | |
1018 | 1019 | void ide_hwif_setup_dma(ide_hwif_t *, const struct ide_port_info *); |
1019 | 1020 | #else |
1020 | 1021 | static inline void ide_hwif_setup_dma(ide_hwif_t *hwif, |