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; }
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); } } }
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); }