Blame view
drivers/ide/palm_bk3710.c
10.7 KB
7c7e92a92 Palmchip BK3710 I... |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
/* * Palmchip bk3710 IDE controller * * Copyright (C) 2006 Texas Instruments. * Copyright (C) 2007 MontaVista Software, Inc., <source@mvista.com> * * ---------------------------------------------------------------------------- * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * ---------------------------------------------------------------------------- * */ #include <linux/types.h> #include <linux/module.h> #include <linux/kernel.h> #include <linux/ioport.h> |
7c7e92a92 Palmchip BK3710 I... |
30 31 32 33 34 35 36 37 38 39 40 |
#include <linux/ide.h> #include <linux/delay.h> #include <linux/init.h> #include <linux/clk.h> #include <linux/platform_device.h> /* Offset of the primary interface registers */ #define IDE_PALM_ATA_PRI_REG_OFFSET 0x1F0 /* Primary Control Offset */ #define IDE_PALM_ATA_PRI_CTL_OFFSET 0x3F6 |
7c7e92a92 Palmchip BK3710 I... |
41 42 43 |
#define BK3710_BMICP 0x00 #define BK3710_BMISP 0x02 #define BK3710_BMIDTP 0x04 |
7c7e92a92 Palmchip BK3710 I... |
44 |
#define BK3710_IDETIMP 0x40 |
7c7e92a92 Palmchip BK3710 I... |
45 46 |
#define BK3710_IDESTATUS 0x47 #define BK3710_UDMACTL 0x48 |
7c7e92a92 Palmchip BK3710 I... |
47 48 49 50 51 52 53 54 55 56 57 |
#define BK3710_MISCCTL 0x50 #define BK3710_REGSTB 0x54 #define BK3710_REGRCVR 0x58 #define BK3710_DATSTB 0x5C #define BK3710_DATRCVR 0x60 #define BK3710_DMASTB 0x64 #define BK3710_DMARCVR 0x68 #define BK3710_UDMASTB 0x6C #define BK3710_UDMATRP 0x70 #define BK3710_UDMAENV 0x74 #define BK3710_IORDYTMP 0x78 |
7c7e92a92 Palmchip BK3710 I... |
58 |
|
ffab6cf44 palm_bk3710: fix ... |
59 |
static unsigned ideclk_period; /* in nanoseconds */ |
7c7e92a92 Palmchip BK3710 I... |
60 |
|
db2f38c22 palm_bk3710: UDMA... |
61 62 63 64 65 |
struct palm_bk3710_udmatiming { unsigned int rptime; /* tRP -- Ready to pause time (nsec) */ unsigned int cycletime; /* tCYCTYP2/2 -- avg Cycle Time (nsec) */ /* tENV is always a minimum of 20 nsec */ }; |
7c7e92a92 Palmchip BK3710 I... |
66 |
static const struct palm_bk3710_udmatiming palm_bk3710_udmatimings[6] = { |
d7f514352 palm_bk3710: palm... |
67 68 69 70 71 72 |
{ 160, 240 / 2 }, /* UDMA Mode 0 */ { 125, 160 / 2 }, /* UDMA Mode 1 */ { 100, 120 / 2 }, /* UDMA Mode 2 */ { 100, 90 / 2 }, /* UDMA Mode 3 */ { 100, 60 / 2 }, /* UDMA Mode 4 */ { 85, 40 / 2 }, /* UDMA Mode 5 */ |
7c7e92a92 Palmchip BK3710 I... |
73 |
}; |
7c7e92a92 Palmchip BK3710 I... |
74 75 76 77 78 79 80 81 |
static void palm_bk3710_setudmamode(void __iomem *base, unsigned int dev, unsigned int mode) { u8 tenv, trp, t0; u32 val32; u16 val16; /* DMA Data Setup */ |
00fe8b7ac ide: use DIV_ROUN... |
82 |
t0 = DIV_ROUND_UP(palm_bk3710_udmatimings[mode].cycletime, |
ffab6cf44 palm_bk3710: fix ... |
83 84 |
ideclk_period) - 1; tenv = DIV_ROUND_UP(20, ideclk_period) - 1; |
00fe8b7ac ide: use DIV_ROUN... |
85 |
trp = DIV_ROUND_UP(palm_bk3710_udmatimings[mode].rptime, |
ffab6cf44 palm_bk3710: fix ... |
86 |
ideclk_period) - 1; |
7c7e92a92 Palmchip BK3710 I... |
87 |
|
7c7e92a92 Palmchip BK3710 I... |
88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 |
/* udmastb Ultra DMA Access Strobe Width */ val32 = readl(base + BK3710_UDMASTB) & (0xFF << (dev ? 0 : 8)); val32 |= (t0 << (dev ? 8 : 0)); writel(val32, base + BK3710_UDMASTB); /* udmatrp Ultra DMA Ready to Pause Time */ val32 = readl(base + BK3710_UDMATRP) & (0xFF << (dev ? 0 : 8)); val32 |= (trp << (dev ? 8 : 0)); writel(val32, base + BK3710_UDMATRP); /* udmaenv Ultra DMA envelop Time */ val32 = readl(base + BK3710_UDMAENV) & (0xFF << (dev ? 0 : 8)); val32 |= (tenv << (dev ? 8 : 0)); writel(val32, base + BK3710_UDMAENV); /* Enable UDMA for Device */ val16 = readw(base + BK3710_UDMACTL) | (1 << dev); writew(val16, base + BK3710_UDMACTL); } static void palm_bk3710_setdmamode(void __iomem *base, unsigned int dev, unsigned short min_cycle, unsigned int mode) { u8 td, tkw, t0; u32 val32; u16 val16; struct ide_timing *t; int cycletime; t = ide_timing_find_mode(mode); cycletime = max_t(int, t->cycle, min_cycle); /* DMA Data Setup */ |
ffab6cf44 palm_bk3710: fix ... |
122 123 |
t0 = DIV_ROUND_UP(cycletime, ideclk_period); td = DIV_ROUND_UP(t->active, ideclk_period); |
7c7e92a92 Palmchip BK3710 I... |
124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 |
tkw = t0 - td - 1; td -= 1; val32 = readl(base + BK3710_DMASTB) & (0xFF << (dev ? 0 : 8)); val32 |= (td << (dev ? 8 : 0)); writel(val32, base + BK3710_DMASTB); val32 = readl(base + BK3710_DMARCVR) & (0xFF << (dev ? 0 : 8)); val32 |= (tkw << (dev ? 8 : 0)); writel(val32, base + BK3710_DMARCVR); /* Disable UDMA for Device */ val16 = readw(base + BK3710_UDMACTL) & ~(1 << dev); writew(val16, base + BK3710_UDMACTL); } static void palm_bk3710_setpiomode(void __iomem *base, ide_drive_t *mate, unsigned int dev, unsigned int cycletime, unsigned int mode) { u8 t2, t2i, t0; u32 val32; struct ide_timing *t; |
33e86019f palm_bk3710: thos... |
147 |
t = ide_timing_find_mode(XFER_PIO_0 + mode); |
7c7e92a92 Palmchip BK3710 I... |
148 |
/* PIO Data Setup */ |
ffab6cf44 palm_bk3710: fix ... |
149 |
t0 = DIV_ROUND_UP(cycletime, ideclk_period); |
33e86019f palm_bk3710: thos... |
150 |
t2 = DIV_ROUND_UP(t->active, ideclk_period); |
7c7e92a92 Palmchip BK3710 I... |
151 152 153 154 155 156 157 158 159 160 161 |
t2i = t0 - t2 - 1; t2 -= 1; val32 = readl(base + BK3710_DATSTB) & (0xFF << (dev ? 0 : 8)); val32 |= (t2 << (dev ? 8 : 0)); writel(val32, base + BK3710_DATSTB); val32 = readl(base + BK3710_DATRCVR) & (0xFF << (dev ? 0 : 8)); val32 |= (t2i << (dev ? 8 : 0)); writel(val32, base + BK3710_DATRCVR); |
7e59ea21a ide: check drive-... |
162 |
if (mate) { |
0716302ee palm_bk3710: use ... |
163 |
u8 mode2 = mate->pio_mode - XFER_PIO_0; |
7c7e92a92 Palmchip BK3710 I... |
164 165 166 167 168 169 |
if (mode2 < mode) mode = mode2; } /* TASKFILE Setup */ |
ffab6cf44 palm_bk3710: fix ... |
170 171 |
t0 = DIV_ROUND_UP(t->cyc8b, ideclk_period); t2 = DIV_ROUND_UP(t->act8b, ideclk_period); |
7c7e92a92 Palmchip BK3710 I... |
172 173 174 175 176 177 178 179 180 181 182 183 |
t2i = t0 - t2 - 1; t2 -= 1; val32 = readl(base + BK3710_REGSTB) & (0xFF << (dev ? 0 : 8)); val32 |= (t2 << (dev ? 8 : 0)); writel(val32, base + BK3710_REGSTB); val32 = readl(base + BK3710_REGRCVR) & (0xFF << (dev ? 0 : 8)); val32 |= (t2i << (dev ? 8 : 0)); writel(val32, base + BK3710_REGRCVR); } |
8776168ca ide: change ->set... |
184 |
static void palm_bk3710_set_dma_mode(ide_hwif_t *hwif, ide_drive_t *drive) |
7c7e92a92 Palmchip BK3710 I... |
185 186 |
{ int is_slave = drive->dn & 1; |
8776168ca ide: change ->set... |
187 188 |
void __iomem *base = (void *)hwif->dma_base; const u8 xferspeed = drive->dma_mode; |
7c7e92a92 Palmchip BK3710 I... |
189 190 191 192 193 |
if (xferspeed >= XFER_UDMA_0) { palm_bk3710_setudmamode(base, is_slave, xferspeed - XFER_UDMA_0); } else { |
4dde4492d ide: make drive->... |
194 195 |
palm_bk3710_setdmamode(base, is_slave, drive->id[ATA_ID_EIDE_DMA_MIN], |
7c7e92a92 Palmchip BK3710 I... |
196 197 198 |
xferspeed); } } |
e085b3cae ide: change ->set... |
199 |
static void palm_bk3710_set_pio_mode(ide_hwif_t *hwif, ide_drive_t *drive) |
7c7e92a92 Palmchip BK3710 I... |
200 201 202 203 |
{ unsigned int cycle_time; int is_slave = drive->dn & 1; ide_drive_t *mate; |
e085b3cae ide: change ->set... |
204 205 |
void __iomem *base = (void *)hwif->dma_base; const u8 pio = drive->pio_mode - XFER_PIO_0; |
7c7e92a92 Palmchip BK3710 I... |
206 207 208 209 210 |
/* * Obtain the drive PIO data for tuning the Palm Chip registers */ cycle_time = ide_pio_cycle_time(drive, pio); |
7e59ea21a ide: check drive-... |
211 |
mate = ide_get_pair_dev(drive); |
7c7e92a92 Palmchip BK3710 I... |
212 213 214 215 216 217 |
palm_bk3710_setpiomode(base, mate, is_slave, cycle_time, pio); } static void __devinit palm_bk3710_chipinit(void __iomem *base) { /* |
33e86019f palm_bk3710: thos... |
218 219 220 221 |
* REVISIT: the ATA reset signal needs to be managed through a * GPIO, which means it should come from platform_data. Until * we get and use such information, we have to trust that things * have been reset before we get here. |
7c7e92a92 Palmchip BK3710 I... |
222 |
*/ |
7c7e92a92 Palmchip BK3710 I... |
223 224 225 226 227 |
/* * Program the IDETIMP Register Value based on the following assumptions * * (ATA_IDETIMP_IDEEN , ENABLE ) | |
7c7e92a92 Palmchip BK3710 I... |
228 |
* (ATA_IDETIMP_PREPOST1 , DISABLE) | |
7c7e92a92 Palmchip BK3710 I... |
229 |
* (ATA_IDETIMP_PREPOST0 , DISABLE) | |
33e86019f palm_bk3710: thos... |
230 231 232 |
* * DM6446 silicon rev 2.1 and earlier have no observed net benefit * from enabling prefetch/postwrite. |
7c7e92a92 Palmchip BK3710 I... |
233 |
*/ |
33e86019f palm_bk3710: thos... |
234 |
writew(BIT(15), base + BK3710_IDETIMP); |
7c7e92a92 Palmchip BK3710 I... |
235 236 237 238 239 240 241 242 243 244 245 |
/* * UDMACTL Ultra-ATA DMA Control * (ATA_UDMACTL_UDMAP1 , 0 ) | * (ATA_UDMACTL_UDMAP0 , 0 ) * */ writew(0, base + BK3710_UDMACTL); /* * MISCCTL Miscellaneous Conrol Register |
33e86019f palm_bk3710: thos... |
246 247 |
* (ATA_MISCCTL_HWNHLD1P , 1 cycle) * (ATA_MISCCTL_HWNHLD0P , 1 cycle) |
7c7e92a92 Palmchip BK3710 I... |
248 249 |
* (ATA_MISCCTL_TIMORIDE , 1) */ |
33e86019f palm_bk3710: thos... |
250 |
writel(0x001, base + BK3710_MISCCTL); |
7c7e92a92 Palmchip BK3710 I... |
251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 |
/* * IORDYTMP IORDY Timer for Primary Register * (ATA_IORDYTMP_IORDYTMP , 0xffff ) */ writel(0xFFFF, base + BK3710_IORDYTMP); /* * Configure BMISP Register * (ATA_BMISP_DMAEN1 , DISABLE ) | * (ATA_BMISP_DMAEN0 , DISABLE ) | * (ATA_BMISP_IORDYINT , CLEAR) | * (ATA_BMISP_INTRSTAT , CLEAR) | * (ATA_BMISP_DMAERROR , CLEAR) */ writew(0, base + BK3710_BMISP); palm_bk3710_setpiomode(base, NULL, 0, 600, 0); palm_bk3710_setpiomode(base, NULL, 1, 600, 0); } |
c79b60ddf palm_bk3710: use ... |
271 |
|
f454cbe8c ide: ->cable_dete... |
272 |
static u8 palm_bk3710_cable_detect(ide_hwif_t *hwif) |
c79b60ddf palm_bk3710: use ... |
273 274 275 |
{ return ATA_CBL_PATA80; } |
b552a2c1d palm_bk3710: use ... |
276 277 278 |
static int __devinit palm_bk3710_init_dma(ide_hwif_t *hwif, const struct ide_port_info *d) { |
b552a2c1d palm_bk3710: use ... |
279 280 281 282 283 |
printk(KERN_INFO " %s: MMIO-DMA ", hwif->name); if (ide_allocate_dma_engine(hwif)) return -1; |
81e8d5a34 ide: remove ide_s... |
284 |
hwif->dma_base = hwif->io_ports.data_addr - IDE_PALM_ATA_PRI_REG_OFFSET; |
b552a2c1d palm_bk3710: use ... |
285 286 |
return 0; } |
ac95beedf ide: add struct i... |
287 288 289 290 291 |
static const struct ide_port_ops palm_bk3710_ports_ops = { .set_pio_mode = palm_bk3710_set_pio_mode, .set_dma_mode = palm_bk3710_set_dma_mode, .cable_detect = palm_bk3710_cable_detect, }; |
c79b60ddf palm_bk3710: use ... |
292 |
|
a0f403bc5 palm_bk3710: add ... |
293 |
static struct ide_port_info __devinitdata palm_bk3710_port_info = { |
b552a2c1d palm_bk3710: use ... |
294 |
.init_dma = palm_bk3710_init_dma, |
ac95beedf ide: add struct i... |
295 |
.port_ops = &palm_bk3710_ports_ops, |
3f023b013 ide: don't set hw... |
296 |
.dma_ops = &sff_dma_ops, |
c5dd43ec6 ide: add IDE_HFLA... |
297 |
.host_flags = IDE_HFLAG_MMIO, |
c79b60ddf palm_bk3710: use ... |
298 |
.pio_mask = ATA_PIO4, |
c79b60ddf palm_bk3710: use ... |
299 |
.mwdma_mask = ATA_MWDMA2, |
29e52cf79 ide: remove chips... |
300 |
.chipset = ide_palm3710, |
c79b60ddf palm_bk3710: use ... |
301 |
}; |
bfc2f01fc palm_bk3710: impr... |
302 |
static int __init palm_bk3710_probe(struct platform_device *pdev) |
7c7e92a92 Palmchip BK3710 I... |
303 |
{ |
ffab6cf44 palm_bk3710: fix ... |
304 |
struct clk *clk; |
7c7e92a92 Palmchip BK3710 I... |
305 |
struct resource *mem, *irq; |
ef183f6b5 drivers/ide/palm_... |
306 |
void __iomem *base; |
13b8860d1 IDE: palm_bk3710:... |
307 |
unsigned long rate, mem_size; |
6f904d015 ide: add ide_host... |
308 |
int i, rc; |
9f36d3143 ide: remove hw_re... |
309 |
struct ide_hw hw, *hws[] = { &hw }; |
7c7e92a92 Palmchip BK3710 I... |
310 |
|
468b5ef8a IDE: palm_bk3710:... |
311 |
clk = clk_get(&pdev->dev, NULL); |
ffab6cf44 palm_bk3710: fix ... |
312 |
if (IS_ERR(clk)) |
7c7e92a92 Palmchip BK3710 I... |
313 |
return -ENODEV; |
ffab6cf44 palm_bk3710: fix ... |
314 315 |
clk_enable(clk); rate = clk_get_rate(clk); |
ffab6cf44 palm_bk3710: fix ... |
316 |
|
33e86019f palm_bk3710: thos... |
317 318 |
/* NOTE: round *down* to meet minimum timings; we count in clocks */ ideclk_period = 1000000000UL / rate; |
7c7e92a92 Palmchip BK3710 I... |
319 320 321 322 323 324 325 |
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (mem == NULL) { printk(KERN_ERR "failed to get memory region resource "); return -ENODEV; } |
ce42a5494 palm_bk3710: fix ... |
326 |
|
7c7e92a92 Palmchip BK3710 I... |
327 328 329 330 331 332 |
irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0); if (irq == NULL) { printk(KERN_ERR "failed to get IRQ resource "); return -ENODEV; } |
28f65c11f treewide: Convert... |
333 |
mem_size = resource_size(mem); |
13b8860d1 IDE: palm_bk3710:... |
334 |
if (request_mem_region(mem->start, mem_size, "palm_bk3710") == NULL) { |
ce42a5494 palm_bk3710: fix ... |
335 336 337 338 |
printk(KERN_ERR "failed to request memory region "); return -EBUSY; } |
13b8860d1 IDE: palm_bk3710:... |
339 340 341 342 343 344 345 |
base = ioremap(mem->start, mem_size); if (!base) { printk(KERN_ERR "failed to map IO memory "); release_mem_region(mem->start, mem_size); return -ENOMEM; } |
7c7e92a92 Palmchip BK3710 I... |
346 347 |
/* Configure the Palm Chip controller */ |
ef183f6b5 drivers/ide/palm_... |
348 |
palm_bk3710_chipinit(base); |
7c7e92a92 Palmchip BK3710 I... |
349 |
|
33e86019f palm_bk3710: thos... |
350 |
memset(&hw, 0, sizeof(hw)); |
7824bc6b4 palm_bk3710: ide_... |
351 |
for (i = 0; i < IDE_NR_PORTS - 2; i++) |
ef183f6b5 drivers/ide/palm_... |
352 353 354 355 |
hw.io_ports_array[i] = (unsigned long) (base + IDE_PALM_ATA_PRI_REG_OFFSET + i); hw.io_ports.ctl_addr = (unsigned long) (base + IDE_PALM_ATA_PRI_CTL_OFFSET); |
7824bc6b4 palm_bk3710: ide_... |
356 |
hw.irq = irq->start; |
bfc2f01fc palm_bk3710: impr... |
357 |
hw.dev = &pdev->dev; |
7c7e92a92 Palmchip BK3710 I... |
358 |
|
a0f403bc5 palm_bk3710: add ... |
359 360 |
palm_bk3710_port_info.udma_mask = rate < 100000000 ? ATA_UDMA4 : ATA_UDMA5; |
33e86019f palm_bk3710: thos... |
361 |
/* Register the IDE interface with Linux */ |
dca398305 ide: pass number ... |
362 |
rc = ide_host_add(&palm_bk3710_port_info, hws, 1, NULL); |
6f904d015 ide: add ide_host... |
363 |
if (rc) |
7824bc6b4 palm_bk3710: ide_... |
364 |
goto out; |
7c7e92a92 Palmchip BK3710 I... |
365 |
return 0; |
7824bc6b4 palm_bk3710: ide_... |
366 367 368 |
out: printk(KERN_WARNING "Palm Chip BK3710 IDE Register Fail "); |
6f904d015 ide: add ide_host... |
369 |
return rc; |
7c7e92a92 Palmchip BK3710 I... |
370 |
} |
458622fcd ATA/IDE: fix plat... |
371 372 |
/* work with hotplug and coldplug */ MODULE_ALIAS("platform:palm_bk3710"); |
7c7e92a92 Palmchip BK3710 I... |
373 374 375 |
static struct platform_driver platform_bk_driver = { .driver = { .name = "palm_bk3710", |
458622fcd ATA/IDE: fix plat... |
376 |
.owner = THIS_MODULE, |
7c7e92a92 Palmchip BK3710 I... |
377 |
}, |
7c7e92a92 Palmchip BK3710 I... |
378 379 380 381 |
}; static int __init palm_bk3710_init(void) { |
bfc2f01fc palm_bk3710: impr... |
382 |
return platform_driver_probe(&platform_bk_driver, palm_bk3710_probe); |
7c7e92a92 Palmchip BK3710 I... |
383 384 385 386 |
} module_init(palm_bk3710_init); MODULE_LICENSE("GPL"); |