aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ide
diff options
context:
space:
mode:
authorArnd Bergmann <arnd@arndb.de>2008-07-16 14:33:41 -0400
committerBartlomiej Zolnierkiewicz <bzolnier@gmail.com>2008-07-16 14:33:41 -0400
commitba1d0de70d64e68f0e035f00dbb041c1e05b49c9 (patch)
tree37268a3670353e6a313832917b31fe7e07c7c8a7 /drivers/ide
parente48905e9cfffd21861c3521d828ae992a53aac67 (diff)
powerpc/ide: remove mpc8xx-ide driver
This driver was only used by arch/ppc code and is obsolete now with the move to common arch/powerpc code. [bart: port it over IDE tree, remove leftover 'choice' from Kconfig] Signed-off-by: Arnd Bergmann <arnd@arndb.de> Acked-by: Kumar Gala <galak@kernel.crashing.org> Cc: Paul Mackerras <paulus@samba.org> Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
Diffstat (limited to 'drivers/ide')
-rw-r--r--drivers/ide/Kconfig40
-rw-r--r--drivers/ide/ppc/Makefile1
-rw-r--r--drivers/ide/ppc/mpc8xx.c844
3 files changed, 0 insertions, 885 deletions
diff --git a/drivers/ide/Kconfig b/drivers/ide/Kconfig
index 5f4d6ea379f6..21511d47d926 100644
--- a/drivers/ide/Kconfig
+++ b/drivers/ide/Kconfig
@@ -929,46 +929,6 @@ config BLK_DEV_PALMCHIP_BK3710
929 Say Y here if you want to support the onchip IDE controller on the 929 Say Y here if you want to support the onchip IDE controller on the
930 TI DaVinci SoC 930 TI DaVinci SoC
931 931
932
933config BLK_DEV_MPC8xx_IDE
934 tristate "MPC8xx IDE support"
935 depends on 8xx && (LWMON || IVMS8 || IVML24 || TQM8xxL) && IDE=y && BLK_DEV_IDE=y && !PPC_MERGE
936 help
937 This option provides support for IDE on Motorola MPC8xx Systems.
938 Please see 'Type of MPC8xx IDE interface' for details.
939
940 If unsure, say N.
941
942choice
943 prompt "Type of MPC8xx IDE interface"
944 depends on BLK_DEV_MPC8xx_IDE
945 default IDE_8xx_PCCARD
946
947config IDE_8xx_PCCARD
948 bool "8xx_PCCARD"
949 ---help---
950 Select how the IDE devices are connected to the MPC8xx system:
951
952 8xx_PCCARD uses the 8xx internal PCMCIA interface in combination
953 with a PC Card (e.g. ARGOSY portable Hard Disk Adapter),
954 ATA PC Card HDDs or ATA PC Flash Cards (example: TQM8xxL
955 systems)
956
957 8xx_DIRECT is used for directly connected IDE devices using the 8xx
958 internal PCMCIA interface (example: IVMS8 systems)
959
960 EXT_DIRECT is used for IDE devices directly connected to the 8xx
961 bus using some glue logic, but _not_ the 8xx internal
962 PCMCIA interface (example: IDIF860 systems)
963
964config IDE_8xx_DIRECT
965 bool "8xx_DIRECT"
966
967config IDE_EXT_DIRECT
968 bool "EXT_DIRECT"
969
970endchoice
971
972# no isa -> no vlb 932# no isa -> no vlb
973if ISA && (ALPHA || X86 || MIPS) 933if ISA && (ALPHA || X86 || MIPS)
974 934
diff --git a/drivers/ide/ppc/Makefile b/drivers/ide/ppc/Makefile
index 65af5848b28c..74e52adcdf4b 100644
--- a/drivers/ide/ppc/Makefile
+++ b/drivers/ide/ppc/Makefile
@@ -1,3 +1,2 @@
1 1
2obj-$(CONFIG_BLK_DEV_IDE_PMAC) += pmac.o 2obj-$(CONFIG_BLK_DEV_IDE_PMAC) += pmac.o
3obj-$(CONFIG_BLK_DEV_MPC8xx_IDE) += mpc8xx.o
diff --git a/drivers/ide/ppc/mpc8xx.c b/drivers/ide/ppc/mpc8xx.c
deleted file mode 100644
index 33bc699814d7..000000000000
--- a/drivers/ide/ppc/mpc8xx.c
+++ /dev/null
@@ -1,844 +0,0 @@
1/*
2 * Copyright (C) 2000, 2001 Wolfgang Denk, wd@denx.de
3 * Modified for direct IDE interface
4 * by Thomas Lange, thomas@corelatus.com
5 * Modified for direct IDE interface on 8xx without using the PCMCIA
6 * controller
7 * by Steven.Scholz@imc-berlin.de
8 * Moved out of arch/ppc/kernel/m8xx_setup.c, other minor cleanups
9 * by Mathew Locke <mattl@mvista.com>
10 */
11
12#include <linux/errno.h>
13#include <linux/kernel.h>
14#include <linux/mm.h>
15#include <linux/stddef.h>
16#include <linux/unistd.h>
17#include <linux/ptrace.h>
18#include <linux/slab.h>
19#include <linux/user.h>
20#include <linux/tty.h>
21#include <linux/major.h>
22#include <linux/interrupt.h>
23#include <linux/reboot.h>
24#include <linux/init.h>
25#include <linux/ioport.h>
26#include <linux/ide.h>
27#include <linux/bootmem.h>
28
29#include <asm/mpc8xx.h>
30#include <asm/mmu.h>
31#include <asm/processor.h>
32#include <asm/io.h>
33#include <asm/pgtable.h>
34#include <asm/ide.h>
35#include <asm/8xx_immap.h>
36#include <asm/machdep.h>
37#include <asm/irq.h>
38
39#define DRV_NAME "ide-mpc8xx"
40
41static int identify (volatile u8 *p);
42static void print_fixed (volatile u8 *p);
43static void print_funcid (int func);
44static int check_ide_device (unsigned long base);
45
46static void ide_interrupt_ack (void *dev);
47static void m8xx_ide_set_pio_mode(ide_drive_t *drive, const u8 pio);
48
49typedef struct ide_ioport_desc {
50 unsigned long base_off; /* Offset to PCMCIA memory */
51 unsigned long reg_off[IDE_NR_PORTS]; /* controller register offsets */
52 int irq; /* IRQ */
53} ide_ioport_desc_t;
54
55ide_ioport_desc_t ioport_dsc[MAX_HWIFS] = {
56#ifdef IDE0_BASE_OFFSET
57 { IDE0_BASE_OFFSET,
58 {
59 IDE0_DATA_REG_OFFSET,
60 IDE0_ERROR_REG_OFFSET,
61 IDE0_NSECTOR_REG_OFFSET,
62 IDE0_SECTOR_REG_OFFSET,
63 IDE0_LCYL_REG_OFFSET,
64 IDE0_HCYL_REG_OFFSET,
65 IDE0_SELECT_REG_OFFSET,
66 IDE0_STATUS_REG_OFFSET,
67 IDE0_CONTROL_REG_OFFSET,
68 IDE0_IRQ_REG_OFFSET,
69 },
70 IDE0_INTERRUPT,
71 },
72#ifdef IDE1_BASE_OFFSET
73 { IDE1_BASE_OFFSET,
74 {
75 IDE1_DATA_REG_OFFSET,
76 IDE1_ERROR_REG_OFFSET,
77 IDE1_NSECTOR_REG_OFFSET,
78 IDE1_SECTOR_REG_OFFSET,
79 IDE1_LCYL_REG_OFFSET,
80 IDE1_HCYL_REG_OFFSET,
81 IDE1_SELECT_REG_OFFSET,
82 IDE1_STATUS_REG_OFFSET,
83 IDE1_CONTROL_REG_OFFSET,
84 IDE1_IRQ_REG_OFFSET,
85 },
86 IDE1_INTERRUPT,
87 },
88#endif /* IDE1_BASE_OFFSET */
89#endif /* IDE0_BASE_OFFSET */
90};
91
92struct ide_timing ide_pio_clocks[6];
93int hold_time[6] = {30, 20, 15, 10, 10, 10 }; /* PIO Mode 5 with IORDY (nonstandard) */
94
95/*
96 * Warning: only 1 (ONE) PCMCIA slot supported here,
97 * which must be correctly initialized by the firmware (PPCBoot).
98 */
99static int _slot_ = -1; /* will be read from PCMCIA registers */
100
101/* Make clock cycles and always round up */
102#define PCMCIA_MK_CLKS( t, T ) (( (t) * ((T)/1000000) + 999U ) / 1000U )
103
104#define M8XX_PCMCIA_CD2(slot) (0x10000000 >> (slot << 4))
105#define M8XX_PCMCIA_CD1(slot) (0x08000000 >> (slot << 4))
106
107/*
108 * The TQM850L hardware has two pins swapped! Grrrrgh!
109 */
110#ifdef CONFIG_TQM850L
111#define __MY_PCMCIA_GCRX_CXRESET PCMCIA_GCRX_CXOE
112#define __MY_PCMCIA_GCRX_CXOE PCMCIA_GCRX_CXRESET
113#else
114#define __MY_PCMCIA_GCRX_CXRESET PCMCIA_GCRX_CXRESET
115#define __MY_PCMCIA_GCRX_CXOE PCMCIA_GCRX_CXOE
116#endif
117
118#if defined(CONFIG_BLK_DEV_MPC8xx_IDE) && defined(CONFIG_IDE_8xx_PCCARD)
119#define PCMCIA_SCHLVL IDE0_INTERRUPT /* Status Change Interrupt Level */
120static int pcmcia_schlvl = PCMCIA_SCHLVL;
121#endif
122
123/*
124 * See include/linux/ide.h for definition of hw_regs_t (p, base)
125 */
126
127/*
128 * m8xx_ide_init_ports() for a direct IDE interface _using_
129 * MPC8xx's internal PCMCIA interface
130 */
131#if defined(CONFIG_IDE_8xx_PCCARD) || defined(CONFIG_IDE_8xx_DIRECT)
132static int __init m8xx_ide_init_ports(hw_regs_t *hw, unsigned long data_port)
133{
134 unsigned long *p = hw->io_ports_array;
135 int i;
136
137 typedef struct {
138 ulong br;
139 ulong or;
140 } pcmcia_win_t;
141 volatile pcmcia_win_t *win;
142 volatile pcmconf8xx_t *pcmp;
143
144 uint *pgcrx;
145 u32 pcmcia_phy_base;
146 u32 pcmcia_phy_end;
147 static unsigned long pcmcia_base = 0;
148 unsigned long base;
149
150 *p = 0;
151
152 pcmp = (pcmconf8xx_t *)(&(((immap_t *)IMAP_ADDR)->im_pcmcia));
153
154 if (!pcmcia_base) {
155 /*
156 * Read out PCMCIA registers. Since the reset values
157 * are undefined, we sure hope that they have been
158 * set up by firmware
159 */
160
161 /* Scan all registers for valid settings */
162 pcmcia_phy_base = 0xFFFFFFFF;
163 pcmcia_phy_end = 0;
164 /* br0 is start of brX and orX regs */
165 win = (pcmcia_win_t *) \
166 (&(((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pbr0));
167 for (i = 0; i < 8; i++) {
168 if (win->or & 1) { /* This bank is marked as valid */
169 if (win->br < pcmcia_phy_base) {
170 pcmcia_phy_base = win->br;
171 }
172 if ((win->br + PCMCIA_MEM_SIZE) > pcmcia_phy_end) {
173 pcmcia_phy_end = win->br + PCMCIA_MEM_SIZE;
174 }
175 /* Check which slot that has been defined */
176 _slot_ = (win->or >> 2) & 1;
177
178 } /* Valid bank */
179 win++;
180 } /* for */
181
182 printk ("PCMCIA slot %c: phys mem %08x...%08x (size %08x)\n",
183 'A' + _slot_,
184 pcmcia_phy_base, pcmcia_phy_end,
185 pcmcia_phy_end - pcmcia_phy_base);
186
187 if (!request_mem_region(pcmcia_phy_base,
188 pcmcia_phy_end - pcmcia_phy_base,
189 DRV_NAME)) {
190 printk(KERN_ERR "%s: resources busy\n", DRV_NAME);
191 return -EBUSY;
192 }
193
194 pcmcia_base=(unsigned long)ioremap(pcmcia_phy_base,
195 pcmcia_phy_end-pcmcia_phy_base);
196
197#ifdef DEBUG
198 printk ("PCMCIA virt base: %08lx\n", pcmcia_base);
199#endif
200 /* Compute clock cycles for PIO timings */
201 for (i=0; i<6; ++i) {
202 bd_t *binfo = (bd_t *)__res;
203 struct ide_timing *t, *n;
204
205 hold_time[i] =
206 PCMCIA_MK_CLKS (hold_time[i],
207 binfo->bi_busfreq);
208
209 t = ide_timing_find_mode(XFER_PIO_0 + i);
210 n = &ide_pio_clocks[i];
211
212 n->setup = PCMCIA_MK_CLKS(t->setup, binfo->bi_busfreq);
213 n->active = PCMCIA_MK_CLKS(t->active, binfo->bi_busfreq);
214 n->cycle = PCMCIA_MK_CLKS(t->cycle, binfo->bi_busfreq);
215#if 0
216 printk ("PIO mode %d timings: %d/%d/%d => %d/%d/%d\n",
217 i,
218 t->setup, t->active, t->cycle,
219 n->setup, n->active, n->cycle);
220#endif
221 }
222 }
223
224 if (_slot_ == -1) {
225 printk ("PCMCIA slot has not been defined! Using A as default\n");
226 _slot_ = 0;
227 }
228
229#ifdef CONFIG_IDE_8xx_PCCARD
230
231#ifdef DEBUG
232 printk ("PIPR = 0x%08X slot %c ==> mask = 0x%X\n",
233 pcmp->pcmc_pipr,
234 'A' + _slot_,
235 M8XX_PCMCIA_CD1(_slot_) | M8XX_PCMCIA_CD2(_slot_) );
236#endif /* DEBUG */
237
238 if (pcmp->pcmc_pipr & (M8XX_PCMCIA_CD1(_slot_)|M8XX_PCMCIA_CD2(_slot_))) {
239 printk ("No card in slot %c: PIPR=%08x\n",
240 'A' + _slot_, (u32) pcmp->pcmc_pipr);
241 return -ENODEV; /* No card in slot */
242 }
243
244 check_ide_device (pcmcia_base);
245
246#endif /* CONFIG_IDE_8xx_PCCARD */
247
248 base = pcmcia_base + ioport_dsc[data_port].base_off;
249#ifdef DEBUG
250 printk ("base: %08x + %08x = %08x\n",
251 pcmcia_base, ioport_dsc[data_port].base_off, base);
252#endif
253
254 for (i = 0; i < IDE_NR_PORTS; ++i) {
255#ifdef DEBUG
256 printk ("port[%d]: %08x + %08x = %08x\n",
257 i,
258 base,
259 ioport_dsc[data_port].reg_off[i],
260 i, base + ioport_dsc[data_port].reg_off[i]);
261#endif
262 *p++ = base + ioport_dsc[data_port].reg_off[i];
263 }
264
265 hw->irq = ioport_dsc[data_port].irq;
266 hw->ack_intr = (ide_ack_intr_t *)ide_interrupt_ack;
267
268#ifdef CONFIG_IDE_8xx_PCCARD
269 {
270 unsigned int reg;
271
272 if (_slot_)
273 pgcrx = &((immap_t *) IMAP_ADDR)->im_pcmcia.pcmc_pgcrb;
274 else
275 pgcrx = &((immap_t *) IMAP_ADDR)->im_pcmcia.pcmc_pgcra;
276
277 reg = *pgcrx;
278 reg |= mk_int_int_mask (pcmcia_schlvl) << 24;
279 reg |= mk_int_int_mask (pcmcia_schlvl) << 16;
280 *pgcrx = reg;
281 }
282#endif /* CONFIG_IDE_8xx_PCCARD */
283
284 /* Enable Harddisk Interrupt,
285 * and make it edge sensitive
286 */
287 /* (11-18) Set edge detect for irq, no wakeup from low power mode */
288 ((immap_t *)IMAP_ADDR)->im_siu_conf.sc_siel |=
289 (0x80000000 >> ioport_dsc[data_port].irq);
290
291#ifdef CONFIG_IDE_8xx_PCCARD
292 /* Make sure we don't get garbage irq */
293 ((immap_t *) IMAP_ADDR)->im_pcmcia.pcmc_pscr = 0xFFFF;
294
295 /* Enable falling edge irq */
296 pcmp->pcmc_per = 0x100000 >> (16 * _slot_);
297#endif /* CONFIG_IDE_8xx_PCCARD */
298
299 hw->chipset = ide_generic;
300
301 return 0;
302}
303#endif /* CONFIG_IDE_8xx_PCCARD || CONFIG_IDE_8xx_DIRECT */
304
305/*
306 * m8xx_ide_init_ports() for a direct IDE interface _not_ using
307 * MPC8xx's internal PCMCIA interface
308 */
309#if defined(CONFIG_IDE_EXT_DIRECT)
310static int __init m8xx_ide_init_ports(hw_regs_t *hw, unsigned long data_port)
311{
312 unsigned long *p = hw->io_ports_array;
313 int i;
314
315 u32 ide_phy_base;
316 u32 ide_phy_end;
317 static unsigned long ide_base = 0;
318 unsigned long base;
319
320 *p = 0;
321
322 if (!ide_base) {
323
324 /* TODO:
325 * - add code to read ORx, BRx
326 */
327 ide_phy_base = CFG_ATA_BASE_ADDR;
328 ide_phy_end = CFG_ATA_BASE_ADDR + 0x200;
329
330 printk ("IDE phys mem : %08x...%08x (size %08x)\n",
331 ide_phy_base, ide_phy_end,
332 ide_phy_end - ide_phy_base);
333
334 if (!request_mem_region(ide_phy_base, 0x200, DRV_NAME)) {
335 printk(KERN_ERR "%s: resources busy\n", DRV_NAME);
336 return -EBUSY;
337 }
338
339 ide_base=(unsigned long)ioremap(ide_phy_base,
340 ide_phy_end-ide_phy_base);
341
342#ifdef DEBUG
343 printk ("IDE virt base: %08lx\n", ide_base);
344#endif
345 }
346
347 base = ide_base + ioport_dsc[data_port].base_off;
348#ifdef DEBUG
349 printk ("base: %08x + %08x = %08x\n",
350 ide_base, ioport_dsc[data_port].base_off, base);
351#endif
352
353 for (i = 0; i < IDE_NR_PORTS; ++i) {
354#ifdef DEBUG
355 printk ("port[%d]: %08x + %08x = %08x\n",
356 i,
357 base,
358 ioport_dsc[data_port].reg_off[i],
359 i, base + ioport_dsc[data_port].reg_off[i]);
360#endif
361 *p++ = base + ioport_dsc[data_port].reg_off[i];
362 }
363
364 /* direct connected IDE drive, i.e. external IRQ */
365 hw->irq = ioport_dsc[data_port].irq;
366 hw->ack_intr = (ide_ack_intr_t *)ide_interrupt_ack;
367
368 /* Enable Harddisk Interrupt,
369 * and make it edge sensitive
370 */
371 /* (11-18) Set edge detect for irq, no wakeup from low power mode */
372 ((immap_t *) IMAP_ADDR)->im_siu_conf.sc_siel |=
373 (0x80000000 >> ioport_dsc[data_port].irq);
374
375 hw->chipset = ide_generic;
376
377 return 0;
378}
379#endif /* CONFIG_IDE_8xx_DIRECT */
380
381
382/* -------------------------------------------------------------------- */
383
384
385/* PCMCIA Timing */
386#ifndef PCMCIA_SHT
387#define PCMCIA_SHT(t) ((t & 0x0F)<<16) /* Strobe Hold Time */
388#define PCMCIA_SST(t) ((t & 0x0F)<<12) /* Strobe Setup Time */
389#define PCMCIA_SL(t) ((t==32) ? 0 : ((t & 0x1F)<<7)) /* Strobe Length */
390#endif
391
392/* Calculate PIO timings */
393static void m8xx_ide_set_pio_mode(ide_drive_t *drive, const u8 pio)
394{
395#if defined(CONFIG_IDE_8xx_PCCARD) || defined(CONFIG_IDE_8xx_DIRECT)
396 volatile pcmconf8xx_t *pcmp;
397 ulong timing, mask, reg;
398
399 pcmp = (pcmconf8xx_t *)(&(((immap_t *)IMAP_ADDR)->im_pcmcia));
400
401 mask = ~(PCMCIA_SHT(0xFF) | PCMCIA_SST(0xFF) | PCMCIA_SL(0xFF));
402
403 timing = PCMCIA_SHT(hold_time[pio] )
404 | PCMCIA_SST(ide_pio_clocks[pio].setup)
405 | PCMCIA_SL (ide_pio_clocks[pio].active)
406 ;
407
408#if 1
409 printk ("Setting timing bits 0x%08lx in PCMCIA controller\n", timing);
410#endif
411 if ((reg = pcmp->pcmc_por0 & mask) != 0)
412 pcmp->pcmc_por0 = reg | timing;
413
414 if ((reg = pcmp->pcmc_por1 & mask) != 0)
415 pcmp->pcmc_por1 = reg | timing;
416
417 if ((reg = pcmp->pcmc_por2 & mask) != 0)
418 pcmp->pcmc_por2 = reg | timing;
419
420 if ((reg = pcmp->pcmc_por3 & mask) != 0)
421 pcmp->pcmc_por3 = reg | timing;
422
423 if ((reg = pcmp->pcmc_por4 & mask) != 0)
424 pcmp->pcmc_por4 = reg | timing;
425
426 if ((reg = pcmp->pcmc_por5 & mask) != 0)
427 pcmp->pcmc_por5 = reg | timing;
428
429 if ((reg = pcmp->pcmc_por6 & mask) != 0)
430 pcmp->pcmc_por6 = reg | timing;
431
432 if ((reg = pcmp->pcmc_por7 & mask) != 0)
433 pcmp->pcmc_por7 = reg | timing;
434
435#elif defined(CONFIG_IDE_EXT_DIRECT)
436
437 printk("%s[%d] %s: not implemented yet!\n",
438 __FILE__, __LINE__, __func__);
439#endif /* defined(CONFIG_IDE_8xx_PCCARD) || defined(CONFIG_IDE_8xx_PCMCIA */
440}
441
442static const struct ide_port_ops m8xx_port_ops = {
443 .set_pio_mode = m8xx_ide_set_pio_mode,
444};
445
446static void
447ide_interrupt_ack (void *dev)
448{
449#ifdef CONFIG_IDE_8xx_PCCARD
450 u_int pscr, pipr;
451
452#if (PCMCIA_SOCKETS_NO == 2)
453 u_int _slot_;
454#endif
455
456 /* get interrupt sources */
457
458 pscr = ((volatile immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pscr;
459 pipr = ((volatile immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pipr;
460
461 /*
462 * report only if both card detect signals are the same
463 * not too nice done,
464 * we depend on that CD2 is the bit to the left of CD1...
465 */
466
467 if(_slot_==-1){
468 printk("PCMCIA slot has not been defined! Using A as default\n");
469 _slot_=0;
470 }
471
472 if(((pipr & M8XX_PCMCIA_CD2(_slot_)) >> 1) ^
473 (pipr & M8XX_PCMCIA_CD1(_slot_)) ) {
474 printk ("card detect interrupt\n");
475 }
476 /* clear the interrupt sources */
477 ((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pscr = pscr;
478
479#else /* ! CONFIG_IDE_8xx_PCCARD */
480 /*
481 * Only CONFIG_IDE_8xx_PCCARD is using the interrupt of the
482 * MPC8xx's PCMCIA controller, so there is nothing to be done here
483 * for CONFIG_IDE_8xx_DIRECT and CONFIG_IDE_EXT_DIRECT.
484 * The interrupt is handled somewhere else. -- Steven
485 */
486#endif /* CONFIG_IDE_8xx_PCCARD */
487}
488
489
490
491/*
492 * CIS Tupel codes
493 */
494#define CISTPL_NULL 0x00
495#define CISTPL_DEVICE 0x01
496#define CISTPL_LONGLINK_CB 0x02
497#define CISTPL_INDIRECT 0x03
498#define CISTPL_CONFIG_CB 0x04
499#define CISTPL_CFTABLE_ENTRY_CB 0x05
500#define CISTPL_LONGLINK_MFC 0x06
501#define CISTPL_BAR 0x07
502#define CISTPL_PWR_MGMNT 0x08
503#define CISTPL_EXTDEVICE 0x09
504#define CISTPL_CHECKSUM 0x10
505#define CISTPL_LONGLINK_A 0x11
506#define CISTPL_LONGLINK_C 0x12
507#define CISTPL_LINKTARGET 0x13
508#define CISTPL_NO_LINK 0x14
509#define CISTPL_VERS_1 0x15
510#define CISTPL_ALTSTR 0x16
511#define CISTPL_DEVICE_A 0x17
512#define CISTPL_JEDEC_C 0x18
513#define CISTPL_JEDEC_A 0x19
514#define CISTPL_CONFIG 0x1a
515#define CISTPL_CFTABLE_ENTRY 0x1b
516#define CISTPL_DEVICE_OC 0x1c
517#define CISTPL_DEVICE_OA 0x1d
518#define CISTPL_DEVICE_GEO 0x1e
519#define CISTPL_DEVICE_GEO_A 0x1f
520#define CISTPL_MANFID 0x20
521#define CISTPL_FUNCID 0x21
522#define CISTPL_FUNCE 0x22
523#define CISTPL_SWIL 0x23
524#define CISTPL_END 0xff
525
526/*
527 * CIS Function ID codes
528 */
529#define CISTPL_FUNCID_MULTI 0x00
530#define CISTPL_FUNCID_MEMORY 0x01
531#define CISTPL_FUNCID_SERIAL 0x02
532#define CISTPL_FUNCID_PARALLEL 0x03
533#define CISTPL_FUNCID_FIXED 0x04
534#define CISTPL_FUNCID_VIDEO 0x05
535#define CISTPL_FUNCID_NETWORK 0x06
536#define CISTPL_FUNCID_AIMS 0x07
537#define CISTPL_FUNCID_SCSI 0x08
538
539/*
540 * Fixed Disk FUNCE codes
541 */
542#define CISTPL_IDE_INTERFACE 0x01
543
544#define CISTPL_FUNCE_IDE_IFACE 0x01
545#define CISTPL_FUNCE_IDE_MASTER 0x02
546#define CISTPL_FUNCE_IDE_SLAVE 0x03
547
548/* First feature byte */
549#define CISTPL_IDE_SILICON 0x04
550#define CISTPL_IDE_UNIQUE 0x08
551#define CISTPL_IDE_DUAL 0x10
552
553/* Second feature byte */
554#define CISTPL_IDE_HAS_SLEEP 0x01
555#define CISTPL_IDE_HAS_STANDBY 0x02
556#define CISTPL_IDE_HAS_IDLE 0x04
557#define CISTPL_IDE_LOW_POWER 0x08
558#define CISTPL_IDE_REG_INHIBIT 0x10
559#define CISTPL_IDE_HAS_INDEX 0x20
560#define CISTPL_IDE_IOIS16 0x40
561
562
563/* -------------------------------------------------------------------- */
564
565
566#define MAX_TUPEL_SZ 512
567#define MAX_FEATURES 4
568
569static int check_ide_device (unsigned long base)
570{
571 volatile u8 *ident = NULL;
572 volatile u8 *feature_p[MAX_FEATURES];
573 volatile u8 *p, *start;
574 int n_features = 0;
575 u8 func_id = ~0;
576 u8 code, len;
577 unsigned short config_base = 0;
578 int found = 0;
579 int i;
580
581#ifdef DEBUG
582 printk ("PCMCIA MEM: %08lX\n", base);
583#endif
584 start = p = (volatile u8 *) base;
585
586 while ((p - start) < MAX_TUPEL_SZ) {
587
588 code = *p; p += 2;
589
590 if (code == 0xFF) { /* End of chain */
591 break;
592 }
593
594 len = *p; p += 2;
595#ifdef DEBUG_PCMCIA
596 { volatile u8 *q = p;
597 printk ("\nTuple code %02x length %d\n\tData:",
598 code, len);
599
600 for (i = 0; i < len; ++i) {
601 printk (" %02x", *q);
602 q+= 2;
603 }
604 }
605#endif /* DEBUG_PCMCIA */
606 switch (code) {
607 case CISTPL_VERS_1:
608 ident = p + 4;
609 break;
610 case CISTPL_FUNCID:
611 func_id = *p;
612 break;
613 case CISTPL_FUNCE:
614 if (n_features < MAX_FEATURES)
615 feature_p[n_features++] = p;
616 break;
617 case CISTPL_CONFIG:
618 config_base = (*(p+6) << 8) + (*(p+4));
619 default:
620 break;
621 }
622 p += 2 * len;
623 }
624
625 found = identify (ident);
626
627 if (func_id != ((u8)~0)) {
628 print_funcid (func_id);
629
630 if (func_id == CISTPL_FUNCID_FIXED)
631 found = 1;
632 else
633 return (1); /* no disk drive */
634 }
635
636 for (i=0; i<n_features; ++i) {
637 print_fixed (feature_p[i]);
638 }
639
640 if (!found) {
641 printk ("unknown card type\n");
642 return (1);
643 }
644
645 /* set level mode irq and I/O mapped device in config reg*/
646 *((u8 *)(base + config_base)) = 0x41;
647
648 return (0);
649}
650
651/* ------------------------------------------------------------------------- */
652
653static void print_funcid (int func)
654{
655 switch (func) {
656 case CISTPL_FUNCID_MULTI:
657 printk (" Multi-Function");
658 break;
659 case CISTPL_FUNCID_MEMORY:
660 printk (" Memory");
661 break;
662 case CISTPL_FUNCID_SERIAL:
663 printk (" Serial Port");
664 break;
665 case CISTPL_FUNCID_PARALLEL:
666 printk (" Parallel Port");
667 break;
668 case CISTPL_FUNCID_FIXED:
669 printk (" Fixed Disk");
670 break;
671 case CISTPL_FUNCID_VIDEO:
672 printk (" Video Adapter");
673 break;
674 case CISTPL_FUNCID_NETWORK:
675 printk (" Network Adapter");
676 break;
677 case CISTPL_FUNCID_AIMS:
678 printk (" AIMS Card");
679 break;
680 case CISTPL_FUNCID_SCSI:
681 printk (" SCSI Adapter");
682 break;
683 default:
684 printk (" Unknown");
685 break;
686 }
687 printk (" Card\n");
688}
689
690/* ------------------------------------------------------------------------- */
691
692static void print_fixed (volatile u8 *p)
693{
694 if (p == NULL)
695 return;
696
697 switch (*p) {
698 case CISTPL_FUNCE_IDE_IFACE:
699 { u8 iface = *(p+2);
700
701 printk ((iface == CISTPL_IDE_INTERFACE) ? " IDE" : " unknown");
702 printk (" interface ");
703 break;
704 }
705 case CISTPL_FUNCE_IDE_MASTER:
706 case CISTPL_FUNCE_IDE_SLAVE:
707 { u8 f1 = *(p+2);
708 u8 f2 = *(p+4);
709
710 printk ((f1 & CISTPL_IDE_SILICON) ? " [silicon]" : " [rotating]");
711
712 if (f1 & CISTPL_IDE_UNIQUE)
713 printk (" [unique]");
714
715 printk ((f1 & CISTPL_IDE_DUAL) ? " [dual]" : " [single]");
716
717 if (f2 & CISTPL_IDE_HAS_SLEEP)
718 printk (" [sleep]");
719
720 if (f2 & CISTPL_IDE_HAS_STANDBY)
721 printk (" [standby]");
722
723 if (f2 & CISTPL_IDE_HAS_IDLE)
724 printk (" [idle]");
725
726 if (f2 & CISTPL_IDE_LOW_POWER)
727 printk (" [low power]");
728
729 if (f2 & CISTPL_IDE_REG_INHIBIT)
730 printk (" [reg inhibit]");
731
732 if (f2 & CISTPL_IDE_HAS_INDEX)
733 printk (" [index]");
734
735 if (f2 & CISTPL_IDE_IOIS16)
736 printk (" [IOis16]");
737
738 break;
739 }
740 }
741 printk ("\n");
742}
743
744/* ------------------------------------------------------------------------- */
745
746
747#define MAX_IDENT_CHARS 64
748#define MAX_IDENT_FIELDS 4
749
750static u8 *known_cards[] = {
751 "ARGOSY PnPIDE D5",
752 NULL
753};
754
755static int identify (volatile u8 *p)
756{
757 u8 id_str[MAX_IDENT_CHARS];
758 u8 data;
759 u8 *t;
760 u8 **card;
761 int i, done;
762
763 if (p == NULL)
764 return (0); /* Don't know */
765
766 t = id_str;
767 done =0;
768
769 for (i=0; i<=4 && !done; ++i, p+=2) {
770 while ((data = *p) != '\0') {
771 if (data == 0xFF) {
772 done = 1;
773 break;
774 }
775 *t++ = data;
776 if (t == &id_str[MAX_IDENT_CHARS-1]) {
777 done = 1;
778 break;
779 }
780 p += 2;
781 }
782 if (!done)
783 *t++ = ' ';
784 }
785 *t = '\0';
786 while (--t > id_str) {
787 if (*t == ' ')
788 *t = '\0';
789 else
790 break;
791 }
792 printk ("Card ID: %s\n", id_str);
793
794 for (card=known_cards; *card; ++card) {
795 if (strcmp(*card, id_str) == 0) { /* found! */
796 return (1);
797 }
798 }
799
800 return (0); /* don't know */
801}
802
803static int __init mpc8xx_ide_probe(void)
804{
805 hw_regs_t hw;
806 u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
807
808#ifdef IDE0_BASE_OFFSET
809 memset(&hw, 0, sizeof(hw));
810 if (!m8xx_ide_init_ports(&hw, 0)) {
811 ide_hwif_t *hwif = ide_find_port();
812
813 if (hwif) {
814 ide_init_port_hw(hwif, &hw);
815 hwif->pio_mask = ATA_PIO4;
816 hwif->port_ops = &m8xx_port_ops;
817
818 idx[0] = hwif->index;
819 }
820 }
821#ifdef IDE1_BASE_OFFSET
822 memset(&hw, 0, sizeof(hw));
823 if (!m8xx_ide_init_ports(&hw, 1)) {
824 ide_hwif_t *mate = ide_find_port();
825
826 if (mate) {
827 ide_init_port_hw(mate, &hw);
828 mate->pio_mask = ATA_PIO4;
829 mate->port_ops = &m8xx_port_ops;
830
831 idx[1] = mate->index;
832 }
833 }
834#endif
835#endif
836
837 ide_device_add(idx, NULL);
838
839 return 0;
840}
841
842module_init(mpc8xx_ide_probe);
843
844MODULE_LICENSE("GPL");