patch-2.4.3 linux/arch/ppc/kernel/m8xx_setup.c

Next file: linux/arch/ppc/kernel/open_pic.c
Previous file: linux/arch/ppc/kernel/m8260_setup.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.4.2/linux/arch/ppc/kernel/m8xx_setup.c linux/arch/ppc/kernel/m8xx_setup.c
@@ -32,6 +32,7 @@
 #include <linux/init.h>
 #include <linux/blk.h>
 #include <linux/ioport.h>
+#include <asm/mpc8xx.h>  /* Before ide.h to avoid warning: `MAX_HWIFS' redefined */
 #include <linux/ide.h>
 #include <linux/bootmem.h>
 
@@ -41,7 +42,6 @@
 #include <asm/io.h>
 #include <asm/pgtable.h>
 #include <asm/ide.h>
-#include <asm/mpc8xx.h>
 #include <asm/8xx_immap.h>
 #include <asm/machdep.h>
 
@@ -52,19 +52,65 @@
 unsigned long m8xx_get_rtc_time(void);
 void m8xx_calibrate_decr(void);
 
-#if 0
-extern int mackbd_setkeycode(unsigned int scancode, unsigned int keycode);
-extern int mackbd_getkeycode(unsigned int scancode);
-extern int mackbd_pretranslate(unsigned char scancode, char raw_mode);
-extern int mackbd_translate(unsigned char scancode, unsigned char *keycode,
-			   char raw_mode);
-extern char mackbd_unexpected_up(unsigned char keycode);
-extern void mackbd_leds(unsigned char leds);
-extern void mackbd_init_hw(void);
-#endif
-
 unsigned char __res[sizeof(bd_t)];
 unsigned long empty_zero_page[1024];
+#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
+
+#ifdef	CONFIG_BLK_DEV_MPC8xx_IDE
+#include "../../../drivers/ide/ide_modes.h"
+
+static void m8xx_ide_tuneproc(ide_drive_t *drive, byte pio);
+
+typedef	struct ide_ioport_desc {
+	unsigned long	base_off;		/* Offset to PCMCIA memory */
+	ide_ioreg_t	reg_off[IDE_NR_PORTS];	/* controller reg. offsets */
+	int		irq;			/* IRQ	*/
+} ide_ioport_desc_t;
+
+ide_ioport_desc_t ioport_dsc[MAX_HWIFS] = {
+#ifdef IDE0_BASE_OFFSET
+	{ IDE0_BASE_OFFSET,
+	    {
+		IDE0_DATA_REG_OFFSET,
+		IDE0_ERROR_REG_OFFSET,
+		IDE0_NSECTOR_REG_OFFSET,
+		IDE0_SECTOR_REG_OFFSET,
+		IDE0_LCYL_REG_OFFSET,
+		IDE0_HCYL_REG_OFFSET,
+		IDE0_SELECT_REG_OFFSET,
+		IDE0_STATUS_REG_OFFSET,
+		IDE0_CONTROL_REG_OFFSET,
+		IDE0_IRQ_REG_OFFSET,
+	    },
+	    IDE0_INTERRUPT,
+	},
+# ifdef IDE1_BASE_OFFSET
+	{ IDE1_BASE_OFFSET,
+	    {
+		IDE1_DATA_REG_OFFSET,
+		IDE1_ERROR_REG_OFFSET,
+		IDE1_NSECTOR_REG_OFFSET,
+		IDE1_SECTOR_REG_OFFSET,
+		IDE1_LCYL_REG_OFFSET,
+		IDE1_HCYL_REG_OFFSET,
+		IDE1_SELECT_REG_OFFSET,
+		IDE1_STATUS_REG_OFFSET,
+		IDE1_CONTROL_REG_OFFSET,
+		IDE1_IRQ_REG_OFFSET,
+	    },
+	    IDE1_INTERRUPT,
+	},
+# endif /* IDE1_BASE_OFFSET */
+#endif	/* IDE0_BASE_OFFSET */
+};
+
+ide_pio_timings_t ide_pio_clocks[6];
+
+/* Make clock cycles and always round up */
+#define PCMCIA_MK_CLKS( t, T ) (( (t) * (T) + 999U ) / 1000U )
+
+#endif	/* CONFIG_BLK_DEV_MPC8xx_IDE */
+#endif	/* CONFIG_BLK_DEV_IDE || CONFIG_BLK_DEV_IDE_MODULE */
 
 #ifdef CONFIG_BLK_DEV_RAM
 extern int rd_doload;		/* 1 = load ramdisk, 0 = don't load */
@@ -77,6 +123,8 @@
 extern unsigned long find_available_memory(void);
 extern void m8xx_cpm_reset(uint);
 
+static void ide_interrupt_handler(void* dev_id);
+
 void __init adbdev_init(void)
 {
 }
@@ -85,12 +133,9 @@
 m8xx_setup_arch(void)
 {
 	int	cpm_page;
-	extern char cmd_line[];
 	
 	cpm_page = (int) alloc_bootmem_pages(PAGE_SIZE);
 	
-	printk("Boot arguments: %s\n", cmd_line);
-
 	/* Reset the Communication Processor Module.
 	*/
 	m8xx_cpm_reset(cpm_page);
@@ -137,7 +182,7 @@
 */
 void timebase_interrupt(int irq, void * dev, struct pt_regs * regs)
 {
-	printk("timebase_interrupt()\n");
+	printk ("timebase_interrupt()\n");
 }
 
 /* The decrementer counts at the system (internal) clock frequency divided by
@@ -164,7 +209,7 @@
 	fp = (binfo->bi_intfreq * 1000000) / 16;
 	freq = fp*60;	/* try to make freq/1e6 an integer */
         divisor = 60;
-        printk("time_init: decrementer frequency = %d/%d\n", freq, divisor);
+        printk("Decrementer Frequency = %d/%d\n", freq, divisor);
         tb_ticks_per_jiffy = freq / HZ / divisor;
 	tb_to_us = mulhwu_scale_factor(freq / divisor, 1000000);
 
@@ -232,9 +277,21 @@
 void
 m8xx_restart(char *cmd)
 {
-	extern void m8xx_gorom(void);
+	__volatile__ unsigned char dummy;
+	uint	msr;
 
-	m8xx_gorom();
+	cli();
+	((immap_t *)IMAP_ADDR)->im_clkrst.car_plprcr |= 0x00000080;
+
+	/* Clear the ME bit in MSR to cause checkstop on machine check
+	*/
+	__asm__("mfmsr %0" : "=r" (msr) );
+	msr &= ~0x1000;
+	__asm__("mtmsr %0" : : "r" (msr) );
+
+	dummy = ((immap_t *)IMAP_ADDR)->im_clkrst.res[0];
+	printk("Restart failed\n"); 
+	while(1);
 }
 
 void
@@ -257,8 +314,8 @@
 
 	bp = (bd_t *)__res;
 			
-	len += sprintf(len+buffer,"clock\t\t: %dMHz\n"
-		       "bus clock\t: %dMHz\n",
+	len += sprintf(len+buffer,"clock\t\t: %ldMHz\n"
+		       "bus clock\t: %ldMHz\n",
 		       bp->bi_intfreq /*/ 1000000*/,
 		       bp->bi_busfreq /*/ 1000000*/);
 
@@ -298,17 +355,13 @@
 
 #if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
 
-/* Define this to make a PCMCIA ATA Flash card work.
-*/
-#define ATA_FLASH 1
-
 /*
  * IDE stuff.
  */
 void
 m8xx_ide_insw(ide_ioreg_t port, void *buf, int ns)
 {
-#ifdef ATA_FLASH
+#ifdef CONFIG_BLK_DEV_MPC8xx_IDE
 	ide_insw(port, buf, ns);
 #else
 	ide_insw(port+_IO_BASE, buf, ns);
@@ -318,7 +371,7 @@
 void
 m8xx_ide_outsw(ide_ioreg_t port, void *buf, int ns)
 {
-#ifdef ATA_FLASH
+#ifdef CONFIG_BLK_DEV_MPC8xx_IDE
 	ide_outsw(port, buf, ns);
 #else
 	ide_outsw(port+_IO_BASE, buf, ns);
@@ -328,8 +381,11 @@
 int
 m8xx_ide_default_irq(ide_ioreg_t base)
 {
-#ifdef ATA_FLASH
-	return PCMCIA_INTERRUPT;
+#ifdef CONFIG_BLK_DEV_MPC8xx_IDE
+	if (base >= MAX_HWIFS)
+		return 0;
+	
+	return (ioport_dsc[base].irq);
 #else
         return 14;
 #endif
@@ -348,60 +404,105 @@
 		       const char *device,
 		       void *dev_id)
 {
-#ifdef ATA_FLASH
+#ifdef CONFIG_BLK_DEV_MPC8xx_IDE
 	return request_8xxirq(irq, handler, flags, device, dev_id);
 #else
 	return request_irq(irq, handler, flags, device, dev_id);
 #endif
 }
 
-/* We can use an external IDE controller or wire the IDE interface to
- * the internal PCMCIA controller.
+/* We can use an external IDE controller
+ * or wire the IDE interface to the internal PCMCIA controller.
+ *
+ * See include/linux/ide.h for definition of hw_regs_t (p, base)
  */
-void __init m8xx_ide_init_hwif_ports(ide_ioreg_t *p, ide_ioreg_t base, int *irq)
+void m8xx_ide_init_hwif_ports(hw_regs_t *hw,
+	ide_ioreg_t data_port, ide_ioreg_t ctrl_port, int *irq)
 {
-	ide_ioreg_t port = base;
+	ide_ioreg_t *p = hw->io_ports;
 	int i;
-#ifdef ATA_FLASH
+#ifdef CONFIG_BLK_DEV_MPC8xx_IDE
 	volatile pcmconf8xx_t	*pcmp;
+
+	static unsigned long pcmcia_base = 0;
+#else
+	ide_ioreg_t port = data_port;	/* ??? XXX ??? XXX */
 #endif
+	unsigned long base;
 
-#ifdef ATA_FLASH
+#ifdef CONFIG_BLK_DEV_MPC8xx_IDE
 	*p = 0;
-	*irq = 0;
+	if (irq)
+		*irq = 0;
+
+	pcmp = (pcmconf8xx_t *)(&(((immap_t *)IMAP_ADDR)->im_pcmcia));
 
-	if (base != 0)		/* Only map the first ATA flash drive */
+	if (!pcmcia_base) {
+		/* relies PCMCIA registers being set up by firmware */
+		pcmcia_base = (unsigned long) ioremap(PCMCIA_MEM_ADDR,
+						      PCMCIA_MEM_SIZE);
+
+		/* Compute clock cycles for PIO timings */
+		for (i=0; i<6; ++i) {
+			bd_t	*binfo = (bd_t *)__res;
+
+			ide_pio_clocks[i].hold_time   =
+				PCMCIA_MK_CLKS (ide_pio_timings[i].hold_time,
+						binfo->bi_busfreq);
+			ide_pio_clocks[i].setup_time  =
+				PCMCIA_MK_CLKS (ide_pio_timings[i].setup_time,
+						binfo->bi_busfreq);
+			ide_pio_clocks[i].active_time =
+				PCMCIA_MK_CLKS (ide_pio_timings[i].active_time,
+						binfo->bi_busfreq);
+			ide_pio_clocks[i].cycle_time  =
+				PCMCIA_MK_CLKS (ide_pio_timings[i].cycle_time,
+						binfo->bi_busfreq);
+#if 0
+			printk ("PIO mode %d timings: %d/%d/%d => %d/%d/%d\n",
+				i,
+				ide_pio_clocks[i].setup_time,
+				ide_pio_clocks[i].active_time,
+				ide_pio_clocks[i].hold_time,
+				ide_pio_clocks[i].cycle_time,
+				ide_pio_timings[i].setup_time,
+				ide_pio_timings[i].active_time,
+				ide_pio_timings[i].hold_time,
+				ide_pio_timings[i].cycle_time);
+#endif
+		}
+	}
+
+	if (data_port >= MAX_HWIFS)
 		return;
 
-	pcmp = (pcmconf8xx_t *)(&(((immap_t *)IMAP_ADDR)->im_pcmcia));
+	base = pcmcia_base + ioport_dsc[data_port].base_off;
+
+# if (!defined(CONFIG_SPD823TS) && !defined(CONFIG_IVMS8))
+	/* SPD823TS and IVMS8 have a direct connection */
 	if (pcmp->pcmc_pipr & 0x18000000)
 		return;		/* No card in slot */
+# endif	/* CONFIG_SPD823TS, CONFIG_IVMS8 */
 
-	base = (unsigned long) ioremap(PCMCIA_MEM_ADDR, 0x200);
+	for (i = 0; i < IDE_NR_PORTS; ++i) {
+	 	*p++ = base + ioport_dsc[data_port].reg_off[i];
+	}
 
-	/* For the M-Systems ATA card, the first 8 registers map 1:1.
-	 * The following register, control/Altstatus, is located at 0x0e.
-	 * Following that, the irq offset, is not used, so we place it in
-	 * an unused location, 0x0a.
-	 */
-	*p++ = base + 8;
-	for (i = 1; i < 8; ++i)
-		*p++ = base + i;
-	*p++ = base + 0x0e;		/* control/altstatus */
-	*p = base + 0x0a;		/* IRQ, not used */
-	if (irq)
-		*irq = PCMCIA_INTERRUPT;
+	if (irq) {
+	    *irq = ioport_dsc[data_port].irq;
+	}
 
-	/* Configure the interface for this interrupt.
-	*/
-	pcmp->pcmc_pgcra = (mk_int_int_mask(PCMCIA_INTERRUPT) << 24) |
-		(mk_int_int_mask(PCMCIA_INTERRUPT) << 16);
+	/* register routine to tune PIO mode */
+	ide_hwifs[data_port].tuneproc = m8xx_ide_tuneproc;
 
-	/* Enable status change interrupt from slot A.
-	*/
-	pcmp->pcmc_per = 0xff100000;
-	pcmp->pcmc_pscr = ~0;
-#else
+	/* Enable Harddisk Interrupt,
+	 * and make it edge sensitive
+	 */
+	hw->ack_intr = (ide_ack_intr_t *)ide_interrupt_handler;
+	((immap_t *)IMAP_ADDR)->im_siu_conf.sc_siel |=
+					(0x80000000 >> ioport_dsc[data_port].irq);
+
+#else	/* ! CONFIG_BLK_DEV_MPC8xx_IDE */
 	
 	/* Just a regular IDE drive on some I/O port.
 	*/
@@ -411,10 +512,84 @@
 	*p++ = base + 0x206;
 	if (irq != NULL)
 		*irq = 0;
-#endif
+#endif	/* CONFIG_BLK_DEV_MPC8xx_IDE */
 }
+#endif	/* CONFIG_BLK_DEV_IDE || CONFIG_BLK_DEV_IDE_MODULE */
+
+
+/* -------------------------------------------------------------------- */
+
+#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
+#ifdef CONFIG_BLK_DEV_MPC8xx_IDE
+
+/* PCMCIA Timing */
+#ifndef	PCMCIA_SHT
+#define PCMCIA_SHT(t)	((t & 0x0F)<<16)	/* Strobe Hold  Time 	*/
+#define PCMCIA_SST(t)	((t & 0x0F)<<12)	/* Strobe Setup Time	*/
+#define PCMCIA_SL(t) ((t==32) ? 0 : ((t & 0x1F)<<7)) /* Strobe Length	*/
 #endif
 
+
+/* Calculate PIO timings */
+static void
+m8xx_ide_tuneproc(ide_drive_t *drive, byte pio)
+{
+	volatile pcmconf8xx_t	*pcmp;
+	ide_pio_data_t d;
+	ulong timing, mask, reg;
+
+	pio = ide_get_best_pio_mode(drive, pio, 4, &d);
+
+#if 1
+	printk("%s[%d] %s: best PIO mode: %d\n",
+		__FILE__,__LINE__,__FUNCTION__, pio);
+#endif
+	pcmp = (pcmconf8xx_t *)(&(((immap_t *)IMAP_ADDR)->im_pcmcia));
+
+	mask = ~(PCMCIA_SHT(0xFF) | PCMCIA_SST(0xFF) | PCMCIA_SL(0xFF));
+
+	timing  = PCMCIA_SHT(ide_pio_clocks[pio].hold_time  )
+		| PCMCIA_SST(ide_pio_clocks[pio].setup_time )
+		| PCMCIA_SL (ide_pio_clocks[pio].active_time)
+		;
+
+#if 1
+	printk ("Setting timing bits 0x%08lx in PCMCIA controller\n", timing);
+#endif
+	if ((reg = pcmp->pcmc_por0 & mask) != 0)
+		pcmp->pcmc_por0 = reg | timing;
+
+	if ((reg = pcmp->pcmc_por1 & mask) != 0)
+		pcmp->pcmc_por1 = reg | timing;
+
+	if ((reg = pcmp->pcmc_por2 & mask) != 0)
+		pcmp->pcmc_por2 = reg | timing;
+
+	if ((reg = pcmp->pcmc_por3 & mask) != 0)
+		pcmp->pcmc_por3 = reg | timing;
+
+	if ((reg = pcmp->pcmc_por4 & mask) != 0)
+		pcmp->pcmc_por4 = reg | timing;
+
+	if ((reg = pcmp->pcmc_por5 & mask) != 0)
+		pcmp->pcmc_por5 = reg | timing;
+
+	if ((reg = pcmp->pcmc_por6 & mask) != 0)
+		pcmp->pcmc_por6 = reg | timing;
+
+	if ((reg = pcmp->pcmc_por7 & mask) != 0)
+		pcmp->pcmc_por7 = reg | timing;
+}
+
+void ide_interrupt_handler (void *dev)
+{
+}
+
+#endif	/* CONFIG_BLK_DEV_MPC8xx_IDE */
+#endif	/* CONFIG_BLK_DEV_IDE || CONFIG_BLK_DEV_IDE_MODULE */
+
+/* -------------------------------------------------------------------- */
+
 void __init
 m8xx_init(unsigned long r3, unsigned long r4, unsigned long r5,
 	 unsigned long r6, unsigned long r7)
@@ -490,7 +665,6 @@
         ppc_ide_md.default_io_base = m8xx_ide_default_io_base;
         ppc_ide_md.fix_driveid = ppc_generic_ide_fix_driveid;
         ppc_ide_md.ide_init_hwif = m8xx_ide_init_hwif_ports;
-        ppc_ide_md.ide_request_irq = m8xx_ide_request_irq;
 
         ppc_ide_md.io_base = _IO_BASE;
 #endif		

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)