Commit 226bf386 authored by Andrew Morton's avatar Andrew Morton Committed by Linus Torvalds

[PATCH] ppc64: fix timebase bugs

From: Anton Blanchard <anton@samba.org>

- Consolidate printing of timebase and cpuinfo in /proc/cpuinfo, there were
  many trivial differences between pseries/iseries/pmac.

- Remove ppc_md.setup_residual, no longer needed

- Fix for processors over 2.147GHz, from Jake Moilanen.  We were using a
  signed int to parse the OF property.

- Set some sane defaults for timebase and processor frequency if we fail to
  get the correct values from OF.
parent cf89c45f
...@@ -88,14 +88,11 @@ extern unsigned long loops_per_jiffy; ...@@ -88,14 +88,11 @@ extern unsigned long loops_per_jiffy;
extern unsigned long ppc_proc_freq; extern unsigned long ppc_proc_freq;
extern unsigned long ppc_tb_freq; extern unsigned long ppc_tb_freq;
void void chrp_get_cpuinfo(struct seq_file *m)
chrp_get_cpuinfo(struct seq_file *m)
{ {
struct device_node *root; struct device_node *root;
const char *model = ""; const char *model = "";
seq_printf(m, "timebase\t: %lu\n", ppc_tb_freq);
root = of_find_node_by_path("/"); root = of_find_node_by_path("/");
if (root) if (root)
model = get_property(root, "model", NULL); model = get_property(root, "model", NULL);
...@@ -253,7 +250,6 @@ chrp_init(unsigned long r3, unsigned long r4, unsigned long r5, ...@@ -253,7 +250,6 @@ chrp_init(unsigned long r3, unsigned long r4, unsigned long r5,
#endif #endif
ppc_md.setup_arch = chrp_setup_arch; ppc_md.setup_arch = chrp_setup_arch;
ppc_md.setup_residual = NULL;
ppc_md.get_cpuinfo = chrp_get_cpuinfo; ppc_md.get_cpuinfo = chrp_get_cpuinfo;
if(naca->interrupt_controller == IC_OPEN_PIC) { if(naca->interrupt_controller == IC_OPEN_PIC) {
ppc_md.init_IRQ = pSeries_init_openpic; ppc_md.init_IRQ = pSeries_init_openpic;
...@@ -418,46 +414,64 @@ chrp_progress(char *s, unsigned short hex) ...@@ -418,46 +414,64 @@ chrp_progress(char *s, unsigned short hex)
extern void setup_default_decr(void); extern void setup_default_decr(void);
/* Some sane defaults: 125 MHz timebase, 1GHz processor */
#define DEFAULT_TB_FREQ 125000000UL
#define DEFAULT_PROC_FREQ (DEFAULT_TB_FREQ * 8)
void __init pSeries_calibrate_decr(void) void __init pSeries_calibrate_decr(void)
{ {
struct device_node *cpu; struct device_node *cpu;
struct div_result divres; struct div_result divres;
int *fp; unsigned int *fp;
unsigned long freq, processor_freq; int node_found;
/* /*
* The cpu node should have a timebase-frequency property * The cpu node should have a timebase-frequency property
* to tell us the rate at which the decrementer counts. * to tell us the rate at which the decrementer counts.
*/ */
freq = 16666000; /* hardcoded default */
cpu = of_find_node_by_type(NULL, "cpu"); cpu = of_find_node_by_type(NULL, "cpu");
ppc_tb_freq = DEFAULT_TB_FREQ; /* hardcoded default */
node_found = 0;
if (cpu != 0) { if (cpu != 0) {
fp = (int *) get_property(cpu, "timebase-frequency", NULL); fp = (unsigned int *)get_property(cpu, "timebase-frequency",
if (fp != 0) NULL);
freq = *fp; if (fp != 0) {
node_found = 1;
ppc_tb_freq = *fp;
}
} }
ppc_tb_freq = freq; if (!node_found)
processor_freq = freq; printk(KERN_ERR "WARNING: Estimating decrementer frequency "
"(not found)\n");
ppc_proc_freq = DEFAULT_PROC_FREQ;
node_found = 0;
if (cpu != 0) { if (cpu != 0) {
fp = (int *) get_property(cpu, "clock-frequency", NULL); fp = (unsigned int *)get_property(cpu, "clock-frequency",
if (fp != 0) NULL);
processor_freq = *fp; if (fp != 0) {
node_found = 1;
ppc_proc_freq = *fp;
}
} }
ppc_proc_freq = processor_freq; if (!node_found)
printk(KERN_ERR "WARNING: Estimating processor frequency "
"(not found)\n");
of_node_put(cpu); of_node_put(cpu);
printk("time_init: decrementer frequency = %lu.%.6lu MHz\n", printk(KERN_INFO "time_init: decrementer frequency = %lu.%.6lu MHz\n",
freq/1000000, freq%1000000); ppc_tb_freq/1000000, ppc_tb_freq%1000000);
printk("time_init: processor frequency = %lu.%.6lu MHz\n", printk(KERN_INFO "time_init: processor frequency = %lu.%.6lu MHz\n",
processor_freq/1000000, processor_freq%1000000); ppc_proc_freq/1000000, ppc_proc_freq%1000000);
tb_ticks_per_jiffy = freq / HZ; tb_ticks_per_jiffy = ppc_tb_freq / HZ;
tb_ticks_per_sec = tb_ticks_per_jiffy * HZ; tb_ticks_per_sec = tb_ticks_per_jiffy * HZ;
tb_ticks_per_usec = freq / 1000000; tb_ticks_per_usec = ppc_tb_freq / 1000000;
tb_to_us = mulhwu_scale_factor(freq, 1000000); tb_to_us = mulhwu_scale_factor(ppc_tb_freq, 1000000);
div128_by_32( 1024*1024, 0, tb_ticks_per_sec, &divres ); div128_by_32(1024*1024, 0, tb_ticks_per_sec, &divres);
tb_to_xs = divres.result_low; tb_to_xs = divres.result_low;
setup_default_decr(); setup_default_decr();
} }
...@@ -311,7 +311,6 @@ void __init iSeries_init_early(void) ...@@ -311,7 +311,6 @@ void __init iSeries_init_early(void)
iSeries_recal_titan = HvCallXm_loadTod(); iSeries_recal_titan = HvCallXm_loadTod();
ppc_md.setup_arch = iSeries_setup_arch; ppc_md.setup_arch = iSeries_setup_arch;
ppc_md.setup_residual = iSeries_setup_residual;
ppc_md.get_cpuinfo = iSeries_get_cpuinfo; ppc_md.get_cpuinfo = iSeries_get_cpuinfo;
ppc_md.init_IRQ = iSeries_init_IRQ; ppc_md.init_IRQ = iSeries_init_IRQ;
ppc_md.get_irq = iSeries_get_irq; ppc_md.get_irq = iSeries_get_irq;
...@@ -726,29 +725,6 @@ void __init iSeries_setup_arch(void) ...@@ -726,29 +725,6 @@ void __init iSeries_setup_arch(void)
printk("Processor version = %x\n", systemcfg->processor); printk("Processor version = %x\n", systemcfg->processor);
} }
/*
* int as400_setup_residual()
*
* Description:
* This routine pretty-prints CPU information gathered from the VPD
* for use in /proc/cpuinfo
*
* Input(s):
* *buffer - Buffer into which CPU data is to be printed.
*
* Output(s):
* *buffer - Buffer with CPU data.
*/
void iSeries_setup_residual(struct seq_file *m, int cpu_id)
{
seq_printf(m, "clock\t\t: %lu.%02luMhz\n", procFreqMhz,
procFreqMhzHundreths);
seq_printf(m, "time base\t: %lu.%02luMHz\n", tbFreqMhz,
tbFreqMhzHundreths);
seq_printf(m, "i-cache\t\t: %d\n", systemcfg->iCacheL1LineSize);
seq_printf(m, "d-cache\t\t: %d\n", systemcfg->dCacheL1LineSize);
}
void iSeries_get_cpuinfo(struct seq_file *m) void iSeries_get_cpuinfo(struct seq_file *m)
{ {
seq_printf(m, "machine\t\t: 64-bit iSeries Logical Partition\n"); seq_printf(m, "machine\t\t: 64-bit iSeries Logical Partition\n");
......
...@@ -95,7 +95,6 @@ void __pmac pmac_show_cpuinfo(struct seq_file *m) ...@@ -95,7 +95,6 @@ void __pmac pmac_show_cpuinfo(struct seq_file *m)
PMAC_MB_INFO_MODEL, 0); PMAC_MB_INFO_MODEL, 0);
unsigned int mbflags = pmac_call_feature(PMAC_FTR_GET_MB_INFO, NULL, unsigned int mbflags = pmac_call_feature(PMAC_FTR_GET_MB_INFO, NULL,
PMAC_MB_INFO_FLAGS, 0); PMAC_MB_INFO_FLAGS, 0);
extern unsigned long ppc_tb_freq;
if (pmac_call_feature(PMAC_FTR_GET_MB_INFO, NULL, PMAC_MB_INFO_NAME, if (pmac_call_feature(PMAC_FTR_GET_MB_INFO, NULL, PMAC_MB_INFO_NAME,
(long)&mbname) != 0) (long)&mbname) != 0)
...@@ -130,9 +129,6 @@ void __pmac pmac_show_cpuinfo(struct seq_file *m) ...@@ -130,9 +129,6 @@ void __pmac pmac_show_cpuinfo(struct seq_file *m)
/* Indicate newworld */ /* Indicate newworld */
seq_printf(m, "pmac-generation\t: NewWorld\n"); seq_printf(m, "pmac-generation\t: NewWorld\n");
/* Indicate timebase value */
seq_printf(m, "timebase\t: %lu\n", ppc_tb_freq);
} }
......
...@@ -40,6 +40,7 @@ ...@@ -40,6 +40,7 @@
extern void setup_default_decr(void); extern void setup_default_decr(void);
extern unsigned long ppc_tb_freq; extern unsigned long ppc_tb_freq;
extern unsigned long ppc_proc_freq;
/* Apparently the RTC stores seconds since 1 Jan 1904 */ /* Apparently the RTC stores seconds since 1 Jan 1904 */
#define RTC_OFFSET 2082844800 #define RTC_OFFSET 2082844800
...@@ -155,6 +156,11 @@ void __init pmac_calibrate_decr(void) ...@@ -155,6 +156,11 @@ void __init pmac_calibrate_decr(void)
tb_to_xs = divres.result_low; tb_to_xs = divres.result_low;
ppc_tb_freq = freq; ppc_tb_freq = freq;
fp = (unsigned int *)get_property(cpu, "clock-frequency", NULL);
if (fp == 0)
panic("can't get cpu processor frequency");
ppc_proc_freq = *fp;
setup_default_decr(); setup_default_decr();
} }
...@@ -330,6 +330,7 @@ static int show_cpuinfo(struct seq_file *m, void *v) ...@@ -330,6 +330,7 @@ static int show_cpuinfo(struct seq_file *m, void *v)
unsigned short min; unsigned short min;
if (cpu_id == NR_CPUS) { if (cpu_id == NR_CPUS) {
seq_printf(m, "timebase\t: %lu\n", ppc_tb_freq);
if (ppc_md.get_cpuinfo != NULL) if (ppc_md.get_cpuinfo != NULL)
ppc_md.get_cpuinfo(m); ppc_md.get_cpuinfo(m);
...@@ -363,29 +364,12 @@ static int show_cpuinfo(struct seq_file *m, void *v) ...@@ -363,29 +364,12 @@ static int show_cpuinfo(struct seq_file *m, void *v)
seq_printf(m, "\n"); seq_printf(m, "\n");
#ifdef CONFIG_PPC_PSERIES
/* /*
* Assume here that all clock rates are the same in a * Assume here that all clock rates are the same in a
* smp system. -- Cort * smp system. -- Cort
*/ */
if (systemcfg->platform != PLATFORM_ISERIES_LPAR) { seq_printf(m, "clock\t\t: %lu.%06luMHz\n", ppc_proc_freq / 1000000,
struct device_node *cpu_node; ppc_proc_freq % 1000000);
int *fp;
cpu_node = of_find_node_by_type(NULL, "cpu");
if (cpu_node) {
fp = (int *) get_property(cpu_node, "clock-frequency",
NULL);
if (fp)
seq_printf(m, "clock\t\t: %dMHz\n",
*fp / 1000000);
of_node_put(cpu_node);
}
}
#endif
if (ppc_md.setup_residual != NULL)
ppc_md.setup_residual(m, cpu_id);
seq_printf(m, "revision\t: %hd.%hd\n\n", maj, min); seq_printf(m, "revision\t: %hd.%hd\n\n", maj, min);
......
...@@ -65,8 +65,6 @@ struct machdep_calls { ...@@ -65,8 +65,6 @@ struct machdep_calls {
void (*setup_arch)(void); void (*setup_arch)(void);
/* Optional, may be NULL. */ /* Optional, may be NULL. */
void (*setup_residual)(struct seq_file *m, int cpu_id);
/* Optional, may be NULL. */
void (*get_cpuinfo)(struct seq_file *m); void (*get_cpuinfo)(struct seq_file *m);
void (*init_IRQ)(void); void (*init_IRQ)(void);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment