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
- Lines: 300
- Date:
Fri Aug 2 17:39:42 2002
- Orig file:
linux-2.4.18/arch/arm/mach-sa1100/cpu-sa1110.c
- Orig date:
Thu Oct 11 09:04:57 2001
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)