--- bab1aa677de13ac98940a34eb4fd07c95c1db857 +++ 4a22877264a8314b6be6ff83c13ac9860663b70d @@ -679,6 +679,59 @@ static ssize_t show_bios_limit(struct cp return sprintf(buf, "%u\n", policy->cpuinfo.max_freq); } +#ifdef CONFIG_VDD_USERSPACE +extern ssize_t acpuclk_get_vdd_levels_str(char *buf); +static ssize_t show_vdd_levels(struct kobject *a, struct attribute *b, char *buf) +{ + return acpuclk_get_vdd_levels_str(buf); +} + +extern void acpuclk_set_vdd(unsigned acpu_khz, int vdd); +static ssize_t store_vdd_levels(struct kobject *a, struct attribute *b, const char *buf, size_t count) +{ + int i = 0, j; + int pair[2] = { 0, 0 }; + int sign = 0; + if (count < 1) + return 0; + if (buf[0] == '-') { + sign = -1; + i++; + } + else if (buf[0] == '+') { + sign = 1; + i++; + } + for (j = 0; i < count; i++) { + char c = buf[i]; + if ((c >= '0') && (c <= '9')) { + pair[j] *= 10; + pair[j] += (c - '0'); + } + else if ((c == ' ') || (c == '\t')) { + if (pair[j] != 0) { + j++; + if ((sign != 0) || (j > 1)) + break; + } + } + else + break; + } + if (sign != 0) { + if (pair[0] > 0) + acpuclk_set_vdd(0, sign * pair[0]); + } + else { + if ((pair[0] > 0) && (pair[1] > 0)) + acpuclk_set_vdd((unsigned)pair[0], pair[1]); + else + return -EINVAL; + } + return count; +} +#endif /* CONFIG_VDD_USERSPACE */ + cpufreq_freq_attr_ro_perm(cpuinfo_cur_freq, 0400); cpufreq_freq_attr_ro(cpuinfo_min_freq); cpufreq_freq_attr_ro(cpuinfo_max_freq); @@ -697,6 +750,10 @@ cpufreq_freq_attr_rw(scaling_max_freq); cpufreq_freq_attr_rw(scaling_governor); cpufreq_freq_attr_rw(scaling_setspeed); +#ifdef CONFIG_VDD_USERSPACE +define_one_global_rw(vdd_levels); +#endif + static struct attribute *default_attrs[] = { &cpuinfo_min_freq.attr, &cpuinfo_max_freq.attr, @@ -715,6 +772,18 @@ static struct attribute *default_attrs[] NULL }; +#ifdef CONFIG_VDD_USERSPACE +static struct attribute *vddtbl_attrs[] = { + &vdd_levels.attr, + NULL +}; + +static struct attribute_group vddtbl_attr_group = { + .attrs = vddtbl_attrs, + .name = "vdd_table", +}; +#endif /* CONFIG_VDD_USERSPACE */ + struct kobject *cpufreq_global_kobject; EXPORT_SYMBOL(cpufreq_global_kobject); @@ -2320,6 +2389,9 @@ EXPORT_SYMBOL_GPL(cpufreq_unregister_dri static int __init cpufreq_core_init(void) { int cpu; +#ifdef CONFIG_VDD_USERSPACE + int rc; +#endif /* CONFIG_VDD_USERSPACE */ for_each_possible_cpu(cpu) { per_cpu(cpufreq_policy_cpu, cpu) = -1; @@ -2337,6 +2409,10 @@ static int __init cpufreq_core_init(void #endif register_syscore_ops(&cpufreq_syscore_ops); +#ifdef CONFIG_VDD_USERSPACE + rc = sysfs_create_group(cpufreq_global_kobject, &vddtbl_attr_group); +#endif /* CONFIG_VDD_USERSPACE */ + return 0; } core_initcall(cpufreq_core_init);