arch/sparc/kernel/time_64.c

Source file repositories/reference/linux-study-clean/arch/sparc/kernel/time_64.c

File Facts

System
Linux kernel
Corpus path
arch/sparc/kernel/time_64.c
Extension
.c
Size
21466 bytes
Lines
902
Domain
Architecture Layer
Bucket
arch/sparc
Inferred role
Architecture Layer: exported/initcall integration point
Status
integration implementation candidate

Why This File Exists

CPU and platform-specific kernel glue: boot entry, traps, syscall entry, interrupts, page tables, context switch, and low-level barriers.

Dependency Surface

Detected Declarations

Annotated Snippet

/* Must be after subsys_initcall() so that busses are probed.  Must
 * be before device_initcall() because things like the RTC driver
 * need to see the clock registers.
 */
fs_initcall(clock_init);

/* Return true if this is Hummingbird, aka Ultra-IIe */
static bool is_hummingbird(void)
{
	unsigned long ver, manuf, impl;

	__asm__ __volatile__ ("rdpr %%ver, %0"
			      : "=&r" (ver));
	manuf = ((ver >> 48) & 0xffff);
	impl = ((ver >> 32) & 0xffff);

	return (manuf == 0x17 && impl == 0x13);
}

struct freq_table {
	unsigned long clock_tick_ref;
	unsigned int ref_freq;
};
static DEFINE_PER_CPU(struct freq_table, sparc64_freq_table) = { 0, 0 };

unsigned long sparc64_get_clock_tick(unsigned int cpu)
{
	struct freq_table *ft = &per_cpu(sparc64_freq_table, cpu);

	if (ft->clock_tick_ref)
		return ft->clock_tick_ref;
	return cpu_data(cpu).clock_tick;
}
EXPORT_SYMBOL(sparc64_get_clock_tick);

#ifdef CONFIG_CPU_FREQ

static int sparc64_cpufreq_notifier(struct notifier_block *nb, unsigned long val,
				    void *data)
{
	struct cpufreq_freqs *freq = data;
	unsigned int cpu;
	struct freq_table *ft;

	for_each_cpu(cpu, freq->policy->cpus) {
		ft = &per_cpu(sparc64_freq_table, cpu);

		if (!ft->ref_freq) {
			ft->ref_freq = freq->old;
			ft->clock_tick_ref = cpu_data(cpu).clock_tick;
		}

		if ((val == CPUFREQ_PRECHANGE  && freq->old < freq->new) ||
		    (val == CPUFREQ_POSTCHANGE && freq->old > freq->new)) {
			cpu_data(cpu).clock_tick =
				cpufreq_scale(ft->clock_tick_ref, ft->ref_freq,
					      freq->new);
		}
	}

	return 0;
}

static struct notifier_block sparc64_cpufreq_notifier_block = {
	.notifier_call	= sparc64_cpufreq_notifier
};

static int __init register_sparc64_cpufreq_notifier(void)
{

	cpufreq_register_notifier(&sparc64_cpufreq_notifier_block,
				  CPUFREQ_TRANSITION_NOTIFIER);
	return 0;
}

core_initcall(register_sparc64_cpufreq_notifier);

#endif /* CONFIG_CPU_FREQ */

static int sparc64_next_event(unsigned long delta,
			      struct clock_event_device *evt)
{
	return tick_operations.add_compare(delta) ? -ETIME : 0;
}

static int sparc64_timer_shutdown(struct clock_event_device *evt)
{
	tick_operations.disable_irq();
	return 0;
}

Annotation

Implementation Notes