Blame view

drivers/ide/ht6560b.c 10.4 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
  /*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2
3
4
5
   *  Copyright (C) 1995-2000  Linus Torvalds & author (see below)
   */
  
  /*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
6
7
8
9
10
   *  HT-6560B EIDE-controller support
   *  To activate controller support use kernel parameter "ide0=ht6560b".
   *  Use hdparm utility to enable PIO mode support.
   *
   *  Author:    Mikko Ala-Fossi            <maf@iki.fi>
eb34b2d90   Jan Evert van Grootheest   ht6560b: update e...
11
   *             Jan Evert van Grootheest   <j.e.van.grootheest@caiway.nl>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
12
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
13
   */
2e4ed2955   Bartlomiej Zolnierkiewicz   ht6560b: use driv...
14
  #define DRV_NAME	"ht6560b"
0e7d8d480   Jan Evert van Grootheest   ht6560b: force pr...
15
  #define HT6560B_VERSION "v0.08"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
16

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
17
  #include <linux/module.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
18
19
20
21
22
23
24
  #include <linux/types.h>
  #include <linux/kernel.h>
  #include <linux/delay.h>
  #include <linux/timer.h>
  #include <linux/mm.h>
  #include <linux/ioport.h>
  #include <linux/blkdev.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
  #include <linux/ide.h>
  #include <linux/init.h>
  
  #include <asm/io.h>
  
  /* #define DEBUG */  /* remove comments for DEBUG messages */
  
  /*
   * The special i/o-port that HT-6560B uses to configuration:
   *    bit0 (0x01): "1" selects secondary interface
   *    bit2 (0x04): "1" enables FIFO function
   *    bit5 (0x20): "1" enables prefetched data read function  (???)
   *
   * The special i/o-port that HT-6560A uses to configuration:
   *    bit0 (0x01): "1" selects secondary interface
   *    bit1 (0x02): "1" enables prefetched data read function
   *    bit2 (0x04): "0" enables multi-master system	      (?)
   *    bit3 (0x08): "1" 3 cycle time, "0" 2 cycle time	      (?)
   */
  #define HT_CONFIG_PORT	  0x3e6
5bfb151f1   Joao Ramos   ide: do not acces...
45
46
47
48
49
  
  static inline u8 HT_CONFIG(ide_drive_t *drive)
  {
  	return ((unsigned long)ide_get_drivedata(drive) & 0xff00) >> 8;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
  /*
   * FIFO + PREFETCH (both a/b-model)
   */
  #define HT_CONFIG_DEFAULT 0x1c /* no prefetch */
  /* #define HT_CONFIG_DEFAULT 0x3c */ /* with prefetch */
  #define HT_SECONDARY_IF	  0x01
  #define HT_PREFETCH_MODE  0x20
  
  /*
   * ht6560b Timing values:
   *
   * I reviewed some assembler source listings of htide drivers and found
   * out how they setup those cycle time interfacing values, as they at Holtek
   * call them. IDESETUP.COM that is supplied with the drivers figures out
   * optimal values and fetches those values to drivers. I found out that
23579a2a1   Bartlomiej Zolnierkiewicz   ide: remove IDE_*...
65
   * they use Select register to fetch timings to the ide board right after
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
   * interface switching. After that it was quite easy to add code to
   * ht6560b.c.
   *
   * IDESETUP.COM gave me values 0x24, 0x45, 0xaa, 0xff that worked fine
   * for hda and hdc. But hdb needed higher values to work, so I guess
   * that sometimes it is necessary to give higher value than IDESETUP
   * gives.   [see cmd640.c for an extreme example of this. -ml]
   *
   * Perhaps I should explain something about these timing values:
   * The higher nibble of value is the Recovery Time  (rt) and the lower nibble
   * of the value is the Active Time  (at). Minimum value 2 is the fastest and
   * the maximum value 15 is the slowest. Default values should be 15 for both.
   * So 0x24 means 2 for rt and 4 for at. Each of the drives should have
   * both values, and IDESETUP gives automatically rt=15 st=15 for CDROMs or
   * similar. If value is too small there will be all sorts of failures.
   *
   * Timing byte consists of
   *	High nibble:  Recovery Cycle Time  (rt)
   *	     The valid values range from 2 to 15. The default is 15.
   *
   *	Low nibble:   Active Cycle Time	   (at)
   *	     The valid values range from 2 to 15. The default is 15.
   *
   * You can obtain optimized timing values by running Holtek IDESETUP.COM
   * for DOS. DOS drivers get their timing values from command line, where
   * the first value is the Recovery Time and the second value is the
   * Active Time for each drive. Smaller value gives higher speed.
   * In case of failures you should probably fall back to a higher value.
   */
5bfb151f1   Joao Ramos   ide: do not acces...
95
96
97
98
  static inline u8 HT_TIMING(ide_drive_t *drive)
  {
  	return (unsigned long)ide_get_drivedata(drive) & 0x00ff;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
99
100
101
102
103
104
105
106
107
108
109
110
  #define HT_TIMING_DEFAULT 0xff
  
  /*
   * This routine handles interface switching for the peculiar hardware design
   * on the F.G.I./Holtek HT-6560B VLB IDE interface.
   * The HT-6560B can only enable one IDE port at a time, and requires a
   * silly sequence (below) whenever we switch between primary and secondary.
   */
  
  /*
   * This routine is invoked from ide.c to prepare for access to a given drive.
   */
abb596b25   Sergei Shtylyov   ide: turn selectp...
111
  static void ht6560b_dev_select(ide_drive_t *drive)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
112
  {
23579a2a1   Bartlomiej Zolnierkiewicz   ide: remove IDE_*...
113
  	ide_hwif_t *hwif = drive->hwif;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
114
115
116
117
118
119
  	unsigned long flags;
  	static u8 current_select = 0;
  	static u8 current_timing = 0;
  	u8 select, timing;
  	
  	local_irq_save(flags);
0e7d8d480   Jan Evert van Grootheest   ht6560b: force pr...
120

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
121
122
  	select = HT_CONFIG(drive);
  	timing = HT_TIMING(drive);
0e7d8d480   Jan Evert van Grootheest   ht6560b: force pr...
123
124
125
126
127
  
  	/*
  	 * Need to enforce prefetch sometimes because otherwise
  	 * it'll hang (hard).
  	 */
97100fc81   Bartlomiej Zolnierkiewicz   ide: add device f...
128
129
  	if (drive->media != ide_disk ||
  	    (drive->dev_flags & IDE_DFLAG_PRESENT) == 0)
0e7d8d480   Jan Evert van Grootheest   ht6560b: force pr...
130
  		select |= HT_PREFETCH_MODE;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
131
132
133
  	if (select != current_select || timing != current_timing) {
  		current_select = select;
  		current_timing = timing;
0ecdca26e   Bartlomiej Zolnierkiewicz   ide: use PIO/MMIO...
134
135
136
137
138
  		(void)inb(HT_CONFIG_PORT);
  		(void)inb(HT_CONFIG_PORT);
  		(void)inb(HT_CONFIG_PORT);
  		(void)inb(HT_CONFIG_PORT);
  		outb(select, HT_CONFIG_PORT);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
139
140
141
  		/*
  		 * Set timing for this drive:
  		 */
4c3032d8a   Bartlomiej Zolnierkiewicz   ide: add struct i...
142
143
  		outb(timing, hwif->io_ports.device_addr);
  		(void)inb(hwif->io_ports.status_addr);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
144
145
146
147
148
149
150
  #ifdef DEBUG
  		printk("ht6560b: %s: select=%#x timing=%#x
  ",
  			drive->name, select, timing);
  #endif
  	}
  	local_irq_restore(flags);
abb596b25   Sergei Shtylyov   ide: turn selectp...
151
152
  
  	outb(drive->select | ATA_DEVICE_OBS, hwif->io_ports.device_addr);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
  }
  
  /*
   * Autodetection and initialization of ht6560b
   */
  static int __init try_to_init_ht6560b(void)
  {
  	u8 orig_value;
  	int i;
  	
  	/* Autodetect ht6560b */
  	if ((orig_value = inb(HT_CONFIG_PORT)) == 0xff)
  		return 0;
  	
  	for (i=3;i>0;i--) {
  		outb(0x00, HT_CONFIG_PORT);
  		if (!( (~inb(HT_CONFIG_PORT)) & 0x3f )) {
  			outb(orig_value, HT_CONFIG_PORT);
  			return 0;
  		}
  	}
  	outb(0x00, HT_CONFIG_PORT);
  	if ((~inb(HT_CONFIG_PORT))& 0x3f) {
  		outb(orig_value, HT_CONFIG_PORT);
  		return 0;
  	}
  	/*
  	 * Ht6560b autodetected
  	 */
  	outb(HT_CONFIG_DEFAULT, HT_CONFIG_PORT);
23579a2a1   Bartlomiej Zolnierkiewicz   ide: remove IDE_*...
183
184
  	outb(HT_TIMING_DEFAULT, 0x1f6);	/* Select register */
  	(void)inb(0x1f7);		/* Status register */
0e7d8d480   Jan Evert van Grootheest   ht6560b: force pr...
185
  	printk("ht6560b " HT6560B_VERSION
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
186
187
188
189
  	       ": chipset detected and initialized"
  #ifdef DEBUG
  	       " with debug enabled"
  #endif
0e7d8d480   Jan Evert van Grootheest   ht6560b: force pr...
190
191
  	       "
  "
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
192
193
194
  		);
  	return 1;
  }
26bcb879c   Bartlomiej Zolnierkiewicz   ide: add ide_set{...
195
  static u8 ht_pio2timings(ide_drive_t *drive, const u8 pio)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
196
197
198
  {
  	int active_time, recovery_time;
  	int active_cycles, recovery_cycles;
30e5ee4d1   Bartlomiej Zolnierkiewicz   ide: remove obsol...
199
  	int bus_speed = ide_vlb_clk ? ide_vlb_clk : 50;
ebae41a5a   Bartlomiej Zolnierkiewicz   ide: add "vlb|pci...
200

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
201
          if (pio) {
7dd00083b   Bartlomiej Zolnierkiewicz   ide: add ide_pio_...
202
  		unsigned int cycle_time;
b32b76f72   Bartlomiej Zolnierkiewicz   ht6560b: convert ...
203
  		struct ide_timing *t = ide_timing_find_mode(XFER_PIO_0 + pio);
7dd00083b   Bartlomiej Zolnierkiewicz   ide: add ide_pio_...
204

7dd00083b   Bartlomiej Zolnierkiewicz   ide: add ide_pio_...
205
  		cycle_time = ide_pio_cycle_time(drive, pio);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
206
207
208
209
210
  		/*
  		 *  Just like opti621.c we try to calculate the
  		 *  actual cycle time for recovery and activity
  		 *  according system bus speed.
  		 */
b32b76f72   Bartlomiej Zolnierkiewicz   ht6560b: convert ...
211
212
  		active_time = t->active;
  		recovery_time = cycle_time - active_time - t->setup;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
  		/*
  		 *  Cycle times should be Vesa bus cycles
  		 */
  		active_cycles   = (active_time   * bus_speed + 999) / 1000;
  		recovery_cycles = (recovery_time * bus_speed + 999) / 1000;
  		/*
  		 *  Upper and lower limits
  		 */
  		if (active_cycles   < 2)  active_cycles   = 2;
  		if (recovery_cycles < 2)  recovery_cycles = 2;
  		if (active_cycles   > 15) active_cycles   = 15;
  		if (recovery_cycles > 15) recovery_cycles = 0;  /* 0==16 */
  		
  #ifdef DEBUG
  		printk("ht6560b: drive %s setting pio=%d recovery=%d (%dns) active=%d (%dns)
  ", drive->name, pio, recovery_cycles, recovery_time, active_cycles, active_time);
  #endif
  		
  		return (u8)((recovery_cycles << 4) | active_cycles);
  	} else {
  		
  #ifdef DEBUG
  		printk("ht6560b: drive %s setting pio=0
  ", drive->name);
  #endif
  		
  		return HT_TIMING_DEFAULT;    /* default setting */
  	}
  }
69e88d2a7   Bartlomiej Zolnierkiewicz   ht6560b: fix dead...
242
  static DEFINE_SPINLOCK(ht6560b_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
243
244
245
246
247
  /*
   *  Enable/Disable so called prefetch mode
   */
  static void ht_set_prefetch(ide_drive_t *drive, u8 state)
  {
5bfb151f1   Joao Ramos   ide: do not acces...
248
  	unsigned long flags, config;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
249
  	int t = HT_PREFETCH_MODE << 8;
69e88d2a7   Bartlomiej Zolnierkiewicz   ht6560b: fix dead...
250
251
  
  	spin_lock_irqsave(&ht6560b_lock, flags);
5bfb151f1   Joao Ramos   ide: do not acces...
252
  	config = (unsigned long)ide_get_drivedata(drive);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
253
254
255
256
  	/*
  	 *  Prefetch mode and unmask irq seems to conflict
  	 */
  	if (state) {
5bfb151f1   Joao Ramos   ide: do not acces...
257
  		config |= t;   /* enable prefetch mode */
97100fc81   Bartlomiej Zolnierkiewicz   ide: add device f...
258
259
  		drive->dev_flags |= IDE_DFLAG_NO_UNMASK;
  		drive->dev_flags &= ~IDE_DFLAG_UNMASK;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
260
  	} else {
5bfb151f1   Joao Ramos   ide: do not acces...
261
  		config &= ~t;  /* disable prefetch mode */
97100fc81   Bartlomiej Zolnierkiewicz   ide: add device f...
262
  		drive->dev_flags &= ~IDE_DFLAG_NO_UNMASK;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
263
  	}
69e88d2a7   Bartlomiej Zolnierkiewicz   ht6560b: fix dead...
264

5bfb151f1   Joao Ramos   ide: do not acces...
265
  	ide_set_drivedata(drive, (void *)config);
69e88d2a7   Bartlomiej Zolnierkiewicz   ht6560b: fix dead...
266
  	spin_unlock_irqrestore(&ht6560b_lock, flags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
267
268
269
270
271
  #ifdef DEBUG
  	printk("ht6560b: drive %s prefetch mode %sabled
  ", drive->name, (state ? "en" : "dis"));
  #endif
  }
e085b3cae   Bartlomiej Zolnierkiewicz   ide: change ->set...
272
  static void ht6560b_set_pio_mode(ide_hwif_t *hwif, ide_drive_t *drive)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
273
  {
5bfb151f1   Joao Ramos   ide: do not acces...
274
  	unsigned long flags, config;
e085b3cae   Bartlomiej Zolnierkiewicz   ide: change ->set...
275
  	const u8 pio = drive->pio_mode - XFER_PIO_0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
276
277
278
279
280
281
282
283
  	u8 timing;
  	
  	switch (pio) {
  	case 8:         /* set prefetch off */
  	case 9:         /* set prefetch on */
  		ht_set_prefetch(drive, pio & 1);
  		return;
  	}
69e88d2a7   Bartlomiej Zolnierkiewicz   ht6560b: fix dead...
284

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
285
  	timing = ht_pio2timings(drive, pio);
69e88d2a7   Bartlomiej Zolnierkiewicz   ht6560b: fix dead...
286
287
  
  	spin_lock_irqsave(&ht6560b_lock, flags);
5bfb151f1   Joao Ramos   ide: do not acces...
288
289
290
291
  	config = (unsigned long)ide_get_drivedata(drive);
  	config &= 0xff00;
  	config |= timing;
  	ide_set_drivedata(drive, (void *)config);
69e88d2a7   Bartlomiej Zolnierkiewicz   ht6560b: fix dead...
292
  	spin_unlock_irqrestore(&ht6560b_lock, flags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
293
294
295
296
297
  #ifdef DEBUG
  	printk("ht6560b: drive %s tuned to pio mode %#x timing=%#x
  ", drive->name, pio, timing);
  #endif
  }
e6d95bd14   Bartlomiej Zolnierkiewicz   ide: ->port_init_...
298
  static void __init ht6560b_init_dev(ide_drive_t *drive)
1f2cf8b00   Bartlomiej Zolnierkiewicz   ide: add ->port_i...
299
  {
e6d95bd14   Bartlomiej Zolnierkiewicz   ide: ->port_init_...
300
  	ide_hwif_t *hwif = drive->hwif;
1f2cf8b00   Bartlomiej Zolnierkiewicz   ide: add ->port_i...
301
302
303
304
305
  	/* Setting default configurations for drives. */
  	int t = (HT_CONFIG_DEFAULT << 8) | HT_TIMING_DEFAULT;
  
  	if (hwif->channel)
  		t |= (HT_SECONDARY_IF << 8);
5bfb151f1   Joao Ramos   ide: do not acces...
306
  	ide_set_drivedata(drive, (void *)t);
1f2cf8b00   Bartlomiej Zolnierkiewicz   ide: add ->port_i...
307
  }
90ab5ee94   Rusty Russell   module_param: mak...
308
  static bool probe_ht6560b;
849138827   Bartlomiej Zolnierkiewicz   ide: make legacy ...
309
310
311
  
  module_param_named(probe, probe_ht6560b, bool, 0);
  MODULE_PARM_DESC(probe, "probe for HT6560B chipset");
abb596b25   Sergei Shtylyov   ide: turn selectp...
312
313
314
315
316
317
318
319
320
321
322
323
324
  static const struct ide_tp_ops ht6560b_tp_ops = {
  	.exec_command		= ide_exec_command,
  	.read_status		= ide_read_status,
  	.read_altstatus		= ide_read_altstatus,
  	.write_devctl		= ide_write_devctl,
  
  	.dev_select		= ht6560b_dev_select,
  	.tf_load		= ide_tf_load,
  	.tf_read		= ide_tf_read,
  
  	.input_data		= ide_input_data,
  	.output_data		= ide_output_data,
  };
ac95beedf   Bartlomiej Zolnierkiewicz   ide: add struct i...
325
  static const struct ide_port_ops ht6560b_port_ops = {
e6d95bd14   Bartlomiej Zolnierkiewicz   ide: ->port_init_...
326
  	.init_dev		= ht6560b_init_dev,
ac95beedf   Bartlomiej Zolnierkiewicz   ide: add struct i...
327
  	.set_pio_mode		= ht6560b_set_pio_mode,
ac95beedf   Bartlomiej Zolnierkiewicz   ide: add struct i...
328
  };
e6b53703b   Andi Kleen   sections: fix sec...
329
  static const struct ide_port_info ht6560b_port_info __initconst = {
d92f1a282   Bartlomiej Zolnierkiewicz   ide: manage I/O r...
330
  	.name			= DRV_NAME,
c413b9b94   Bartlomiej Zolnierkiewicz   ide: add struct i...
331
  	.chipset		= ide_ht6560b,
abb596b25   Sergei Shtylyov   ide: turn selectp...
332
  	.tp_ops 		= &ht6560b_tp_ops,
ac95beedf   Bartlomiej Zolnierkiewicz   ide: add struct i...
333
  	.port_ops		= &ht6560b_port_ops,
c413b9b94   Bartlomiej Zolnierkiewicz   ide: add struct i...
334
335
  	.host_flags		= IDE_HFLAG_SERIALIZE | /* is this needed? */
  				  IDE_HFLAG_NO_DMA |
c413b9b94   Bartlomiej Zolnierkiewicz   ide: add struct i...
336
  				  IDE_HFLAG_ABUSE_PREFETCH,
1a1990f54   Jan Evert van Grootheest   ht6560b can only ...
337
  	.pio_mask		= ATA_PIO4,
c413b9b94   Bartlomiej Zolnierkiewicz   ide: add struct i...
338
  };
ade2daf9c   Bartlomiej Zolnierkiewicz   ide: make remaini...
339
  static int __init ht6560b_init(void)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
340
  {
849138827   Bartlomiej Zolnierkiewicz   ide: make legacy ...
341
342
  	if (probe_ht6560b == 0)
  		return -ENODEV;
2e4ed2955   Bartlomiej Zolnierkiewicz   ht6560b: use driv...
343
  	if (!request_region(HT_CONFIG_PORT, 1, DRV_NAME)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
344
345
  		printk(KERN_NOTICE "%s: HT_CONFIG_PORT not found
  ",
eb63963a5   Harvey Harrison   ide: replace rema...
346
  			__func__);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
347
348
349
350
  		return -ENODEV;
  	}
  
  	if (!try_to_init_ht6560b()) {
eb63963a5   Harvey Harrison   ide: replace rema...
351
352
  		printk(KERN_NOTICE "%s: HBA not found
  ", __func__);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
353
354
  		goto release_region;
  	}
0bfeee7d4   Bartlomiej Zolnierkiewicz   ide: use ide_lega...
355
  	return ide_legacy_device_add(&ht6560b_port_info, 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
356
357
358
359
360
  
  release_region:
  	release_region(HT_CONFIG_PORT, 1);
  	return -ENODEV;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
361
  module_init(ht6560b_init);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
362
363
364
365
  
  MODULE_AUTHOR("See Local File");
  MODULE_DESCRIPTION("HT-6560B EIDE-controller support");
  MODULE_LICENSE("GPL");