Linux Power Management development
 help / color / mirror / Atom feed
From: Mason <mpeg.blue@free.fr>
To: Linux ARM <linux-arm-kernel@lists.infradead.org>,
	Linux PM <linux-pm@vger.kernel.org>,
	cpufreq <cpufreq@vger.kernel.org>
Cc: "Rafael J. Wysocki" <rjw@rjwysocki.net>,
	Viresh Kumar <viresh.kumar@linaro.org>
Subject: Re: RFC on cpufreq implementation
Date: Thu, 29 Jan 2015 17:43:19 +0100	[thread overview]
Message-ID: <54CA6327.5070707@free.fr> (raw)
In-Reply-To: <54B7F7CD.7030903@free.fr>

[-- Attachment #1: Type: text/plain, Size: 736 bytes --]

On 15/01/2015 18:24, Mason wrote:

> This is a follow-up to my previous thread.
> "How many frequencies would cpufreq optimally like to manage?"
> http://thread.gmane.org/gmane.linux.ports.arm.kernel/373669

OK, so this is my TAKE 2 on the cpufreq driver, trying to remove
some dependencies on machine-specific definitions by getting the
virtual address at init via ioremap. (Is -EFAULT the right error
to return if ioremap fails?)

I'm not sure where machine-specific information is supposed to
be stored though? Such as register definitions, or the physical
addresses/offsets. What if they need to be shared among several
source files? I can't just duplicate them... (I've tentatively
called it temp.h for the time being.)

Regards.


[-- Attachment #2: cpufreq.c --]
[-- Type: text/x-csrc, Size: 2567 bytes --]

/*
 * Copyright 2015 Sigma Designs
 *
 * 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
 * published by the Free Software Foundation.
 *
 */
#include <linux/module.h>
#include <linux/cpufreq.h>
#include <linux/io.h>
#include "temp.h"

MODULE_LICENSE("GPL");
MODULE_AUTHOR("Sigma Designs");
MODULE_DESCRIPTION("cpufreq driver for Tangox 87xx");

#define TANGOX_XTAL_FREQ	27000 /* in kHz */
#define CLKGEN_BASE		0x10000
#define SYS_clkgen0_pll		(clkgen_base + 0x00)
#define SYS_cpuclk_div_ctrl	(clkgen_base + 0x24)

static void __iomem *clkgen_base;

static struct cpufreq_frequency_table freq_table[] = {
	{ .driver_data = 1 },
	{ .driver_data = 2 },
	{ .driver_data = 3 },
	{ .driver_data = 5 },
	{ .driver_data = 9 },
	{ .frequency = CPUFREQ_TABLE_END },
};

static unsigned int tangox_get_freq(unsigned int cpu)
{
	union SYS_clkgen_pll pll;
	union SYS_clk_div_ctrl div;

	pll.val = readl_relaxed(SYS_clkgen0_pll);
	if (pll.f.Isel != 1 || pll.f.M != 0) return 0;

	div.val = readl_relaxed(SYS_cpuclk_div_ctrl);
	if (div.f.BP != 0 || div.f.F != 0) return 0;

	return TANGOX_XTAL_FREQ * (pll.f.N + 1) / div.f.I >> pll.f.K;
}

static int tangox_target(struct cpufreq_policy *policy, unsigned int index)
{
	while (readl_relaxed(SYS_cpuclk_div_ctrl) >> 31) cpu_relax();
	writel_relaxed(freq_table[index].driver_data, SYS_cpuclk_div_ctrl);
	return 0;
}

static int tangox_cpu_init(struct cpufreq_policy *policy)
{
	struct cpufreq_frequency_table *p;
	unsigned int freq = tangox_get_freq(0);
	unsigned int transition_latency_ns = freq / SYS_FAST_RAMP_SPEED;
	if ((clkgen_base = ioremap(CLKGEN_BASE, 0x40)) == NULL) return -EFAULT;

	for (p = freq_table; p->frequency != CPUFREQ_TABLE_END; ++p) {
		unsigned int I = p->driver_data;
		union SYS_clk_div_ctrl div = SYS_CLK_DIV_CTRL(I);
		p->driver_data = div.val;
		p->frequency = freq / I;
	}

	return cpufreq_generic_init(policy, freq_table, transition_latency_ns);
}

static struct cpufreq_driver tangox_cpufreq_driver = {
	.name		= "tangox-cpufreq",
	.init		= tangox_cpu_init,
	.verify		= cpufreq_generic_frequency_table_verify,
	.target_index	= tangox_target,
	.get		= tangox_get_freq,
	.exit		= cpufreq_generic_exit,
	.attr		= cpufreq_generic_attr,
};

static int __init tangox_cpufreq_init(void)
{
	return cpufreq_register_driver(&tangox_cpufreq_driver);
}

static void __exit tangox_cpufreq_exit(void)
{
	cpufreq_unregister_driver(&tangox_cpufreq_driver);
}

module_init(tangox_cpufreq_init);
module_exit(tangox_cpufreq_exit);

  parent reply	other threads:[~2015-01-29 16:43 UTC|newest]

Thread overview: 18+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-01-15 17:24 RFC on cpufreq implementation Mason
2015-01-16  9:08 ` Krzysztof Kozlowski
2015-01-16 11:10   ` Mason
2015-01-16 11:43     ` Krzysztof Kozlowski
2015-01-16 12:10     ` Javi Merino
2015-01-16 14:00     ` Mason
2015-01-19  7:52 ` Viresh Kumar
2015-01-19 22:03   ` Mason
2015-01-20  3:55     ` Viresh Kumar
2015-01-19  9:22 ` Amit Kucheria
2015-01-19 22:13   ` Mason
2015-01-29 16:43 ` Mason [this message]
2015-01-30  1:15   ` Viresh Kumar
2015-01-30 23:44     ` Mason
2015-02-02  3:58       ` Viresh Kumar
2015-02-04  0:07         ` Mason
2015-02-04  0:32           ` Måns Rullgård
2015-02-04  4:12           ` Viresh Kumar

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=54CA6327.5070707@free.fr \
    --to=mpeg.blue@free.fr \
    --cc=cpufreq@vger.kernel.org \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=linux-pm@vger.kernel.org \
    --cc=rjw@rjwysocki.net \
    --cc=viresh.kumar@linaro.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox