patch-2.4.19 linux-2.4.19/arch/arm/mach-sa1100/cpu-sa1110.c

Next file: linux-2.4.19/arch/arm/mach-sa1100/dma-sa1100.c
Previous file: linux-2.4.19/arch/arm/mach-sa1100/cpu-sa1100.c
Back to the patch index
Back to the overall index

diff -urN linux-2.4.18/arch/arm/mach-sa1100/cpu-sa1110.c linux-2.4.19/arch/arm/mach-sa1100/cpu-sa1110.c
@@ -3,7 +3,7 @@
  *
  *  Copyright (C) 2001 Russell King
  *
- *  $Id: cpu-sa1110.c,v 1.5 2001/09/10 13:25:58 rmk Exp $
+ *  $Id: cpu-sa1110.c,v 1.6 2001/10/22 11:53:47 rmk Exp $
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -29,14 +29,8 @@
 
 #undef DEBUG
 
-extern u_int processor_id;
-
-#define CPU_REVISION	(processor_id & 15)
-#define CPU_SA1110_A0	(0)
-#define CPU_SA1110_B0	(4)
-#define CPU_SA1110_B1	(5)
-#define CPU_SA1110_B2	(6)
-#define CPU_SA1110_B4	(8)
+extern unsigned int sa11x0_freq_to_ppcr(unsigned int khz);
+extern unsigned int sa11x0_validatespeed(unsigned int khz);
 
 struct sdram_params {
 	u_char  rows;		/* bits				 */
@@ -48,6 +42,12 @@
 	u_short refresh;	/* refresh time for array (us)	 */
 };
 
+struct sdram_info {
+	u_int	mdcnfg;
+	u_int	mdrefr;
+	u_int	mdcas[3];
+};
+
 static struct sdram_params tc59sm716_cl2_params __initdata = {
 	rows:		    12,
 	tck:		    10,
@@ -68,6 +68,16 @@
 	cas_latency:	     3,
 };
 
+static struct sdram_params samsung_k4s641632d_tc75 __initdata = {
+	rows:		    14,
+	tck:		     9,
+	trcd:		    27,
+	trp:		    20,
+	twr:		     9,
+	refresh:	 64000,
+	cas_latency:	     3,
+};
+
 static struct sdram_params sdram_params;
 
 /*
@@ -95,10 +105,11 @@
 	mdcas[1]  = mdcas[2] = 0x55555555 << (shift & 1);
 }
 
-static void sdram_update_timing(u_int cpu_khz, struct sdram_params *sdram)
+static void
+sdram_calculate_timing(struct sdram_info *sd, u_int cpu_khz,
+		       struct sdram_params *sdram)
 {
-	u_int mdcnfg, mdrefr, mdcas[3], mem_khz, sd_khz, trp, twr;
-	unsigned long flags;
+	u_int mem_khz, sd_khz, trp, twr;
 
 	mem_khz = cpu_khz / 2;
 	sd_khz = mem_khz;
@@ -114,7 +125,7 @@
 	    (CPU_REVISION < CPU_SA1110_B2 && sd_khz < 62000))
 		sd_khz /= 2;
 
-	mdcnfg = MDCNFG & 0x007f007f;
+	sd->mdcnfg = MDCNFG & 0x007f007f;
 
 	twr = ns_to_cycles(sdram->twr, mem_khz);
 
@@ -123,53 +134,26 @@
 	if (trp < 1)
 		trp = 1;
 
-	mdcnfg |= trp << 8;
-	mdcnfg |= trp << 24;
-	mdcnfg |= sdram->cas_latency << 12;
-	mdcnfg |= sdram->cas_latency << 28;
-	mdcnfg |= twr << 14;
-	mdcnfg |= twr << 30;
+	sd->mdcnfg |= trp << 8;
+	sd->mdcnfg |= trp << 24;
+	sd->mdcnfg |= sdram->cas_latency << 12;
+	sd->mdcnfg |= sdram->cas_latency << 28;
+	sd->mdcnfg |= twr << 14;
+	sd->mdcnfg |= twr << 30;
 
-	mdrefr = MDREFR & 0xffbffff0;
-	mdrefr |= 7;
+	sd->mdrefr = MDREFR & 0xffbffff0;
+	sd->mdrefr |= 7;
 
 	if (sd_khz != mem_khz)
-		mdrefr |= MDREFR_K1DB2;
+		sd->mdrefr |= MDREFR_K1DB2;
 
 	/* initial number of '1's in MDCAS + 1 */
-	set_mdcas(mdcas, sd_khz >= 62000, ns_to_cycles(sdram->trcd, mem_khz));
+	set_mdcas(sd->mdcas, sd_khz >= 62000, ns_to_cycles(sdram->trcd, mem_khz));
 
 #ifdef DEBUG
-	mdelay(250);
 	printk("MDCNFG: %08x MDREFR: %08x MDCAS0: %08x MDCAS1: %08x MDCAS2: %08x\n",
-		mdcnfg, mdrefr, mdcas[0], mdcas[1], mdcas[2]);
+		sd->mdcnfg, sd->mdrefr, sd->mdcas[0], sd->mdcas[1], sd->mdcas[2]);
 #endif
-
-	/*
-	 * Reprogram the DRAM timings with interrupts disabled, and
-	 * ensure that we are doing this within a complete cache line.
-	 * This means that we won't access SDRAM for the duration of
-	 * the programming.
-	 */
-	local_irq_save(flags);
-	asm("mcr p15, 0, %0, c10, c4" : : "r" (0));
-	udelay(10);
-	__asm__("
-		b	1f
-		.align	5
-1:		str	%3, [%1, #28]		@ MDREFR
-		str	%4, [%1, #4]		@ MDCAS0
-		str	%5, [%1, #8]		@ MDCAS1
-		str	%6, [%1, #12]		@ MDCAS2
-		str	%2, [%1, #0]		@ MDCNFG
-		ldr	%0, [%1, #0]
-		nop
-		nop"
-		: "=&r" (mdcnfg)
-		: "r" (io_p2v(_MDCNFG)),
-		  "0" (mdcnfg), "r" (mdrefr),
-		  "r" (mdcas[0]), "r" (mdcas[1]), "r" (mdcas[2]));
-	local_irq_restore(flags);
 }
 
 /*
@@ -203,65 +187,92 @@
 	sdram_set_refresh(dri);
 }
 
-static int
-sdram_notifier(struct notifier_block *nb, unsigned long val, void *data)
+/*
+ * Ok, set the CPU frequency.  Since we've done the validation
+ * above, we can match for an exact frequency.  If we don't find
+ * an exact match, we will to set the lowest frequency to be safe.
+ */
+static void sa1110_setspeed(unsigned int khz)
 {
-	struct cpufreq_info *ci = data;
 	struct sdram_params *sdram = &sdram_params;
+	struct sdram_info sd;
+	unsigned long flags;
+	unsigned int ppcr, unused;
 
-	/* were we initialised? */
-	if (sdram->cas_latency == 0) {
-		struct cpufreq_minmax *m = data;
-		m->min_freq = m->max_freq = m->cur_freq;
-		return 0;
-	}
+	ppcr = sa11x0_freq_to_ppcr(khz);
+	sdram_calculate_timing(&sd, khz, sdram);
 
-	switch (val) {
-	case CPUFREQ_MINMAX:
-		/*
-		 * until we work out why the assabet
-		 * crashes below 147.5MHz...
-		 */
-		cpufreq_updateminmax(data, 147500, -1);
-		break;
-
-	case CPUFREQ_PRECHANGE:
-		/*
-		 * The clock could be going away for some time.
-		 * Set the SDRAMs to refresh rapidly (every 64
-		 * memory clock cycles).  To get through the
-		 * whole array, we need to wait 262144 mclk cycles.
-		 * We wait 20ms to be safe.
-		 */
-		sdram_set_refresh(2);
-		set_current_state(TASK_UNINTERRUPTIBLE);
-		schedule_timeout(20 * HZ / 1000);
-
-		if (ci->old_freq < ci->new_freq)
-			sdram_update_timing(ci->new_freq, sdram);
-		break;
-
-	case CPUFREQ_POSTCHANGE:
-		if (ci->old_freq > ci->new_freq)
-			sdram_update_timing(ci->new_freq, sdram);
-		sdram_update_refresh(ci->new_freq, sdram);
-		break;
+#if 0
+	/*
+	 * These values are wrong according to the SA1110 documentation
+	 * and errata, but they seem to work.  Need to get a storage
+	 * scope on to the SDRAM signals to work out why.
+	 */
+	if (khz < 147500) {
+		sd.mdrefr |= MDREFR_K1DB2;
+		sd.mdcas[0] = 0xaaaaaa7f;
+	} else {
+		sd.mdrefr &= ~MDREFR_K1DB2;
+		sd.mdcas[0] = 0xaaaaaa9f;
 	}
-	return 0;
-}
+	sd.mdcas[1] = 0xaaaaaaaa;
+	sd.mdcas[2] = 0xaaaaaaaa;
+#endif
+	/*
+	 * The clock could be going away for some time.  Set the SDRAMs
+	 * to refresh rapidly (every 64 memory clock cycles).  To get
+	 * through the whole array, we need to wait 262144 mclk cycles.
+	 * We wait 20ms to be safe.
+	 */
+	sdram_set_refresh(2);
+	set_current_state(TASK_UNINTERRUPTIBLE);
+	schedule_timeout(20 * HZ / 1000);
 
-static struct notifier_block sa1110_clkchg_block = {
-	notifier_call:	sdram_notifier,
-};
+	/*
+	 * Reprogram the DRAM timings with interrupts disabled, and
+	 * ensure that we are doing this within a complete cache line.
+	 * This means that we won't access SDRAM for the duration of
+	 * the programming.
+	 */
+	local_irq_save(flags);
+	asm("mcr p15, 0, %0, c10, c4" : : "r" (0));
+	udelay(10);
+	__asm__ __volatile__("
+		b	2f
+		.align	5
+1:		str	%3, [%1, #0]		@ MDCNFG
+		str	%4, [%1, #28]		@ MDREFR
+		str	%5, [%1, #4]		@ MDCAS0
+		str	%6, [%1, #8]		@ MDCAS1
+		str	%7, [%1, #12]		@ MDCAS2
+		str	%8, [%2, #0]		@ PPCR
+		ldr	%0, [%1, #0]
+		b	3f
+2:		b	1b
+3:		nop
+		nop"
+		: "=&r" (unused)
+		: "r" (&MDCNFG), "r" (&PPCR), "0" (sd.mdcnfg),
+		  "r" (sd.mdrefr), "r" (sd.mdcas[0]),
+		  "r" (sd.mdcas[1]), "r" (sd.mdcas[2]), "r" (ppcr));
+	local_irq_restore(flags);
 
-static int __init sa1110_sdram_init(void)
+	/*
+	 * Now, return the SDRAM refresh back to normal.
+	 */
+	sdram_update_refresh(khz, sdram);
+}
+
+static int __init sa1110_clk_init(void)
 {
 	struct sdram_params *sdram = NULL;
-	unsigned int cur_freq = cpufreq_get(smp_processor_id());
 
 	if (machine_is_assabet())
 		sdram = &tc59sm716_cl3_params;
 
+	if (machine_is_pt_system3())
+		sdram = &samsung_k4s641632d_tc75;
+
 	if (sdram) {
 		printk(KERN_DEBUG "SDRAM: tck: %d trcd: %d trp: %d"
 			" twr: %d refresh: %d cas_latency: %d\n",
@@ -270,11 +281,11 @@
 
 		memcpy(&sdram_params, sdram, sizeof(sdram_params));
 
-		sdram_update_timing(cur_freq, &sdram_params);
-		sdram_update_refresh(cur_freq, &sdram_params);
+		sa1110_setspeed(cpufreq_get(0));
+		cpufreq_setfunctions(sa11x0_validatespeed, sa1110_setspeed);
 	}
 
-	return cpufreq_register_notifier(&sa1110_clkchg_block);
+	return 0;
 }
 
-__initcall(sa1110_sdram_init);
+__initcall(sa1110_clk_init);

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