Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1bfb4b21 authored by Vitja Makarov's avatar Vitja Makarov Committed by Bryan Wu
Browse files

[Blackfin] arch: Support for CPU_FREQ and NOHZ

parent 14b03204
Loading
Loading
Loading
Loading
+7 −3
Original line number Original line Diff line number Diff line
@@ -60,7 +60,7 @@ static inline unsigned long long cycles_2_ns(cycle_t cyc)


static cycle_t read_cycles(void)
static cycle_t read_cycles(void)
{
{
	return get_cycles();
	return __bfin_cycles_off + (get_cycles() << __bfin_cycles_mod);
}
}


unsigned long long sched_clock(void)
unsigned long long sched_clock(void)
@@ -117,7 +117,7 @@ static void bfin_timer_set_mode(enum clock_event_mode mode,
		break;
		break;
	}
	}
	case CLOCK_EVT_MODE_ONESHOT:
	case CLOCK_EVT_MODE_ONESHOT:
		bfin_write_TSCALE(0);
		bfin_write_TSCALE(TIME_SCALE - 1);
		bfin_write_TCOUNT(0);
		bfin_write_TCOUNT(0);
		bfin_write_TCNTL(TMPWR | TMREN);
		bfin_write_TCNTL(TMPWR | TMREN);
		CSYNC();
		CSYNC();
@@ -183,10 +183,14 @@ irqreturn_t timer_interrupt(int irq, void *dev_id)


static int __init bfin_clockevent_init(void)
static int __init bfin_clockevent_init(void)
{
{
	unsigned long timer_clk;

	timer_clk = get_cclk() / TIME_SCALE;

	setup_irq(IRQ_CORETMR, &bfin_timer_irq);
	setup_irq(IRQ_CORETMR, &bfin_timer_irq);
	bfin_timer_init();
	bfin_timer_init();


	clockevent_bfin.mult = div_sc(get_cclk(), NSEC_PER_SEC, clockevent_bfin.shift);
	clockevent_bfin.mult = div_sc(timer_clk, NSEC_PER_SEC, clockevent_bfin.shift);
	clockevent_bfin.max_delta_ns = clockevent_delta2ns(-1, &clockevent_bfin);
	clockevent_bfin.max_delta_ns = clockevent_delta2ns(-1, &clockevent_bfin);
	clockevent_bfin.min_delta_ns = clockevent_delta2ns(100, &clockevent_bfin);
	clockevent_bfin.min_delta_ns = clockevent_delta2ns(100, &clockevent_bfin);
	clockevents_register_device(&clockevent_bfin);
	clockevents_register_device(&clockevent_bfin);
+15 −9
Original line number Original line Diff line number Diff line
@@ -62,6 +62,14 @@ static struct bfin_dpm_state {
	unsigned int tscale; /* change the divider on the core timer interrupt */
	unsigned int tscale; /* change the divider on the core timer interrupt */
} dpm_state_table[3];
} dpm_state_table[3];


/*
   normalized to maximum frequncy offset for CYCLES,
   used in time-ts cycles clock source, but could be used
   somewhere also.
 */
unsigned long long __bfin_cycles_off;
unsigned int __bfin_cycles_mod;

/**************************************************************************/
/**************************************************************************/


static unsigned int bfin_getfreq(unsigned int cpu)
static unsigned int bfin_getfreq(unsigned int cpu)
@@ -80,6 +88,7 @@ static int bfin_target(struct cpufreq_policy *policy,
	unsigned int index, plldiv, tscale;
	unsigned int index, plldiv, tscale;
	unsigned long flags, cclk_hz;
	unsigned long flags, cclk_hz;
	struct cpufreq_freqs freqs;
	struct cpufreq_freqs freqs;
	cycles_t cycles;


	if (cpufreq_frequency_table_target(policy, bfin_freq_table,
	if (cpufreq_frequency_table_target(policy, bfin_freq_table,
		 target_freq, relation, &index))
		 target_freq, relation, &index))
@@ -101,8 +110,14 @@ static int bfin_target(struct cpufreq_policy *policy,
		bfin_write_PLL_DIV(plldiv);
		bfin_write_PLL_DIV(plldiv);
		/* we have to adjust the core timer, because it is using cclk */
		/* we have to adjust the core timer, because it is using cclk */
		bfin_write_TSCALE(tscale);
		bfin_write_TSCALE(tscale);
		cycles = get_cycles();
		SSYNC();
		SSYNC();
	cycles += 10; /* ~10 cycles we loose after get_cycles() */
	__bfin_cycles_off += (cycles << __bfin_cycles_mod) - (cycles << index);
	__bfin_cycles_mod = index;
	local_irq_restore(flags);
	local_irq_restore(flags);
	/* TODO: just test case for cycles clock source, remove later */
	pr_debug("cpufreq: done\n");
	cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
	cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);


	return 0;
	return 0;
@@ -119,15 +134,6 @@ static int __init __bfin_cpu_init(struct cpufreq_policy *policy)
	unsigned long cclk, sclk, csel, min_cclk;
	unsigned long cclk, sclk, csel, min_cclk;
	int index;
	int index;


#ifdef CONFIG_CYCLES_CLOCKSOURCE
/*
 * Clocksource CYCLES is still CONTINUOUS but not longer with a constant tick rate in case we enable
 * CPU frequency scaling, since CYCLES runs off Core Clock.
 */
	printk(KERN_WARNING "CPU frequency scaling not supported: Clocksource not suitable\n"
		return -ENODEV;
#endif

	if (policy->cpu != 0)
	if (policy->cpu != 0)
		return -EINVAL;
		return -EINVAL;


+4 −0
Original line number Original line Diff line number Diff line
@@ -24,6 +24,8 @@


#ifndef CONFIG_CPU_FREQ
#ifndef CONFIG_CPU_FREQ
#define TIME_SCALE 1
#define TIME_SCALE 1
#define __bfin_cycles_off (0)
#define __bfin_cycles_mod (0)
#else
#else
/*
/*
 * Blackfin CPU frequency scaling supports max Core Clock 1, 1/2 and 1/4 .
 * Blackfin CPU frequency scaling supports max Core Clock 1, 1/2 and 1/4 .
@@ -31,6 +33,8 @@
 * adjust the Core Timer Presale Register. This way we don't lose time.
 * adjust the Core Timer Presale Register. This way we don't lose time.
 */
 */
#define TIME_SCALE 4
#define TIME_SCALE 4
extern unsigned long long __bfin_cycles_off;
extern unsigned int __bfin_cycles_mod;
#endif
#endif


#endif
#endif