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;
extern unsigned long ppc_proc_freq;
extern unsigned long ppc_tb_freq;
void
chrp_get_cpuinfo(struct seq_file *m)
void chrp_get_cpuinfo(struct seq_file *m)
{
struct device_node *root;
const char *model = "";
seq_printf(m, "timebase\t: %lu\n", ppc_tb_freq);
root = of_find_node_by_path("/");
if (root)
model = get_property(root, "model", NULL);
......@@ -253,7 +250,6 @@ chrp_init(unsigned long r3, unsigned long r4, unsigned long r5,
#endif
ppc_md.setup_arch = chrp_setup_arch;
ppc_md.setup_residual = NULL;
ppc_md.get_cpuinfo = chrp_get_cpuinfo;
if(naca->interrupt_controller == IC_OPEN_PIC) {
ppc_md.init_IRQ = pSeries_init_openpic;
......@@ -418,46 +414,64 @@ chrp_progress(char *s, unsigned short hex)
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)
{
struct device_node *cpu;
struct div_result divres;
int *fp;
unsigned long freq, processor_freq;
unsigned int *fp;
int node_found;
/*
* The cpu node should have a timebase-frequency property
* to tell us the rate at which the decrementer counts.
*/
freq = 16666000; /* hardcoded default */
cpu = of_find_node_by_type(NULL, "cpu");
ppc_tb_freq = DEFAULT_TB_FREQ; /* hardcoded default */
node_found = 0;
if (cpu != 0) {
fp = (int *) get_property(cpu, "timebase-frequency", NULL);
if (fp != 0)
freq = *fp;
fp = (unsigned int *)get_property(cpu, "timebase-frequency",
NULL);
if (fp != 0) {
node_found = 1;
ppc_tb_freq = *fp;
}
}
ppc_tb_freq = freq;
processor_freq = freq;
if (!node_found)
printk(KERN_ERR "WARNING: Estimating decrementer frequency "
"(not found)\n");
ppc_proc_freq = DEFAULT_PROC_FREQ;
node_found = 0;
if (cpu != 0) {
fp = (int *) get_property(cpu, "clock-frequency", NULL);
if (fp != 0)
processor_freq = *fp;
fp = (unsigned int *)get_property(cpu, "clock-frequency",
NULL);
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);
printk("time_init: decrementer frequency = %lu.%.6lu MHz\n",
freq/1000000, freq%1000000);
printk("time_init: processor frequency = %lu.%.6lu MHz\n",
processor_freq/1000000, processor_freq%1000000);
printk(KERN_INFO "time_init: decrementer frequency = %lu.%.6lu MHz\n",
ppc_tb_freq/1000000, ppc_tb_freq%1000000);
printk(KERN_INFO "time_init: processor frequency = %lu.%.6lu MHz\n",
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_usec = freq / 1000000;
tb_to_us = mulhwu_scale_factor(freq, 1000000);
div128_by_32( 1024*1024, 0, tb_ticks_per_sec, &divres );
tb_ticks_per_usec = ppc_tb_freq / 1000000;
tb_to_us = mulhwu_scale_factor(ppc_tb_freq, 1000000);
div128_by_32(1024*1024, 0, tb_ticks_per_sec, &divres);
tb_to_xs = divres.result_low;
setup_default_decr();
}
......@@ -311,7 +311,6 @@ void __init iSeries_init_early(void)
iSeries_recal_titan = HvCallXm_loadTod();
ppc_md.setup_arch = iSeries_setup_arch;
ppc_md.setup_residual = iSeries_setup_residual;
ppc_md.get_cpuinfo = iSeries_get_cpuinfo;
ppc_md.init_IRQ = iSeries_init_IRQ;
ppc_md.get_irq = iSeries_get_irq;
......@@ -726,29 +725,6 @@ void __init iSeries_setup_arch(void)
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)
{
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)
PMAC_MB_INFO_MODEL, 0);
unsigned int mbflags = pmac_call_feature(PMAC_FTR_GET_MB_INFO, NULL,
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,
(long)&mbname) != 0)
......@@ -130,9 +129,6 @@ void __pmac pmac_show_cpuinfo(struct seq_file *m)
/* Indicate newworld */
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 @@
extern void setup_default_decr(void);
extern unsigned long ppc_tb_freq;
extern unsigned long ppc_proc_freq;
/* Apparently the RTC stores seconds since 1 Jan 1904 */
#define RTC_OFFSET 2082844800
......@@ -155,6 +156,11 @@ void __init pmac_calibrate_decr(void)
tb_to_xs = divres.result_low;
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();
}
......@@ -330,6 +330,7 @@ static int show_cpuinfo(struct seq_file *m, void *v)
unsigned short min;
if (cpu_id == NR_CPUS) {
seq_printf(m, "timebase\t: %lu\n", ppc_tb_freq);
if (ppc_md.get_cpuinfo != NULL)
ppc_md.get_cpuinfo(m);
......@@ -363,29 +364,12 @@ static int show_cpuinfo(struct seq_file *m, void *v)
seq_printf(m, "\n");
#ifdef CONFIG_PPC_PSERIES
/*
* Assume here that all clock rates are the same in a
* smp system. -- Cort
*/
if (systemcfg->platform != PLATFORM_ISERIES_LPAR) {
struct device_node *cpu_node;
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, "clock\t\t: %lu.%06luMHz\n", ppc_proc_freq / 1000000,
ppc_proc_freq % 1000000);
seq_printf(m, "revision\t: %hd.%hd\n\n", maj, min);
......
......@@ -65,8 +65,6 @@ struct machdep_calls {
void (*setup_arch)(void);
/* 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 (*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