예제 #1
0
static int
tegra_cpufreq_freq_helper(SYSCTLFN_ARGS)
{
	struct sysctlnode node;
	int fq, oldfq = 0, error;
	uint64_t xc;

	node = *rnode;
	node.sysctl_data = &fq;

	fq = cpufreq_get_rate();
	if (rnode->sysctl_num == cpufreq_node_target)
		oldfq = fq;

	error = sysctl_lookup(SYSCTLFN_CALL(&node));
	if (error || newp == NULL)
		return error;

	if (fq == oldfq || rnode->sysctl_num != cpufreq_node_target)
		return 0;

	if (atomic_cas_uint(&cpufreq_busy, 0, 1) != 0)
		return EBUSY;

	error = cpufreq_set_rate(fq);
	if (error == 0) {
		xc = xc_broadcast(0, tegra_cpufreq_post, NULL, NULL);
		xc_wait(xc);
		pmf_event_inject(NULL, PMFE_SPEED_CHANGED);
	}

	atomic_dec_uint(&cpufreq_busy);

	return error;
}
예제 #2
0
void
amlogic_cpufreq_bootstrap(void)
{
	u_int availfreq[AMLOGIC_CPUFREQ_MAX];

	cpufreq_set_rate = &meson8b_cpu_set_rate;
	cpufreq_get_rate = &meson8b_cpu_get_rate;
	cpufreq_get_available = &meson8b_cpu_get_available;

	if (cpufreq_get_available(availfreq, AMLOGIC_CPUFREQ_MAX) > 0) {
		if (cpufreq_set_rate(availfreq[0]) == 0) {
			amlogic_cpufreq_cb(NULL, NULL);
		}
	}
}
예제 #3
0
void
tegra_cpufreq_init(void)
{
	const struct sysctlnode *node, *cpunode, *freqnode;
	u_int availfreq[TEGRA_CPUFREQ_MAX];
	size_t nfreq;
	int error;

	if (cpufreq_func == NULL)
		return;

	nfreq = cpufreq_get_available(availfreq, TEGRA_CPUFREQ_MAX);
	if (nfreq == 0)
		return;

	KASSERT(nfreq <= TEGRA_CPUFREQ_MAX);

	for (int i = 0; i < nfreq; i++) {
		char buf[6];
		snprintf(buf, sizeof(buf), i ? " %u" : "%u", availfreq[i]);
		strcat(tegra_cpufreq_available, buf);
	}

	error = sysctl_createv(&cpufreq_log, 0, NULL, &node,
	    CTLFLAG_PERMANENT, CTLTYPE_NODE, "machdep", NULL,
	    NULL, 0, NULL, 0, CTL_MACHDEP, CTL_EOL);
	if (error)
		goto sysctl_failed;
	error = sysctl_createv(&cpufreq_log, 0, &node, &cpunode,
	    0, CTLTYPE_NODE, "cpu", NULL,
	    NULL, 0, NULL, 0, CTL_CREATE, CTL_EOL);
	if (error)
		goto sysctl_failed;
	error = sysctl_createv(&cpufreq_log, 0, &cpunode, &freqnode,
	    0, CTLTYPE_NODE, "frequency", NULL,
	    NULL, 0, NULL, 0, CTL_CREATE, CTL_EOL);
	if (error)
		goto sysctl_failed;

	error = sysctl_createv(&cpufreq_log, 0, &freqnode, &node,
	    CTLFLAG_READWRITE, CTLTYPE_INT, "target", NULL,
	    tegra_cpufreq_freq_helper, 0, NULL, 0,
	    CTL_CREATE, CTL_EOL);
	if (error)
		goto sysctl_failed;
	cpufreq_node_target = node->sysctl_num;

	error = sysctl_createv(&cpufreq_log, 0, &freqnode, &node,
	    CTLFLAG_READWRITE, CTLTYPE_INT, "current", NULL,
	    tegra_cpufreq_freq_helper, 0, NULL, 0,
	    CTL_CREATE, CTL_EOL);
	if (error)
		goto sysctl_failed;
	cpufreq_node_current = node->sysctl_num;

	error = sysctl_createv(&cpufreq_log, 0, &freqnode, &node,
	    0, CTLTYPE_STRING, "available", NULL,
	    NULL, 0, tegra_cpufreq_available, 0,
	    CTL_CREATE, CTL_EOL);
	if (error)
		goto sysctl_failed;
	cpufreq_node_available = node->sysctl_num;

#ifdef CPUFREQ_BOOT
	cpufreq_set_rate(CPUFREQ_BOOT);
	tegra_cpufreq_post(NULL, NULL);
#endif

	return;

sysctl_failed:
	aprint_error("cpufreq: couldn't create sysctl nodes (%d)\n", error);
	sysctl_teardown(&cpufreq_log);
}