From 54870df3b8017ed996ad21f6207d6bc7784cbcb0 Mon Sep 17 00:00:00 2001 From: Grazvydas Ignotas Date: Mon, 23 May 2016 01:12:02 +0300 Subject: [PATCH] pandora: add some hacky controls for expansion and 5v supplies --- arch/arm/mach-omap2/board-omap3pandora.c | 173 ++++++++++++++++++++++- 1 file changed, 169 insertions(+), 4 deletions(-) diff --git a/arch/arm/mach-omap2/board-omap3pandora.c b/arch/arm/mach-omap2/board-omap3pandora.c index b9ac6b777e64..397d46a70eeb 100644 --- a/arch/arm/mach-omap2/board-omap3pandora.c +++ b/arch/arm/mach-omap2/board-omap3pandora.c @@ -939,6 +939,11 @@ static struct omap_board_mux board_mux[] __initdata = { #endif static struct regulator *lid_switch_power; +static struct regulator *v5v_power; +static struct regulator *exp_power; +static bool v5v_power_disable_needed; +static bool exp_power_disable_needed; +static struct delayed_work disable_regulators_work; #ifdef CONFIG_PM_SLEEP static int pandora_pm_suspend(struct device *dev) @@ -960,11 +965,54 @@ static int pandora_pm_resume(struct device *dev) static SIMPLE_DEV_PM_OPS(pandora_pm, pandora_pm_suspend, pandora_pm_resume); +static void pandora_disable_regulators(struct work_struct *work) +{ + if (v5v_power_disable_needed) + regulator_disable(v5v_power); + + if (exp_power_disable_needed) + regulator_disable(exp_power); +} + static int __devinit pandora_pm_probe(struct platform_device *pdev) { lid_switch_power = regulator_get(NULL, "lidsw"); if (!IS_ERR(lid_switch_power)) regulator_enable(lid_switch_power); + else + dev_err(&pdev->dev, "regulator_get lidsw: %ld\n", + PTR_ERR(lid_switch_power)); + + /* if regulators are enabled by the bootloaders, take a reference and + * disable them later, after the boot scripts have a chance to + * reconfigure things if they want to, otherwise leave them off */ + v5v_power = regulator_get(NULL, "v5v_force"); + if (!IS_ERR(v5v_power)) { + if (regulator_is_enabled(v5v_power) > 0) { + v5v_power_disable_needed = true; + regulator_enable(v5v_power); + } + } + else { + dev_err(&pdev->dev, "regulator_get v5v_force: %ld\n", + PTR_ERR(v5v_power)); + } + + exp_power = regulator_get(NULL, "exp"); + if (!IS_ERR(exp_power)) { + if (regulator_is_enabled(exp_power) > 0) { + exp_power_disable_needed = true; + regulator_enable(exp_power); + } + } + else { + dev_err(&pdev->dev, "regulator_get exp: %ld\n", + PTR_ERR(exp_power)); + } + + INIT_DELAYED_WORK(&disable_regulators_work, + pandora_disable_regulators); + schedule_delayed_work(&disable_regulators_work, 30 * HZ); return 0; } @@ -1019,17 +1067,134 @@ static void __init omap3pandora_init(void) omap_mux_init_signal("sdrc_cke1", OMAP_PIN_OUTPUT); } -/* HACK: create it here, so that others don't need to bother */ #ifdef CONFIG_PROC_FS #include +#include + +static bool v5v_power_proc_enabled; +static bool exp_power_proc_enabled; + +static int v5v_enable_read(char *page, char **start, off_t off, + int count, int *eof, void *data) +{ + if (IS_ERR_OR_NULL(v5v_power)) + return -ENODEV; + + *eof = 1; + return sprintf(page, "%d\n", v5v_power_proc_enabled); +} + +static int v5v_enable_write(struct file *file, const char __user *buffer, + unsigned long count, void *data) +{ + char buff[32]; + long val; + int ret; + + if (IS_ERR_OR_NULL(v5v_power)) + return -ENODEV; + + count = strncpy_from_user(buff, buffer, + count < sizeof(buff) ? count : sizeof(buff) - 1); + buff[count] = 0; + + ret = strict_strtol(buff, 0, &val); + if (ret < 0) + return ret; + + val = !!val; + if (val == v5v_power_proc_enabled) + return count; + if (val) + ret = regulator_enable(v5v_power); + else + ret = regulator_disable(v5v_power); + if (ret < 0) + return ret; + + v5v_power_proc_enabled = val; + return count; +} + +static int exp_power_read(char *page, char **start, off_t off, + int count, int *eof, void *data) +{ + int ret = 0; + + if (IS_ERR_OR_NULL(exp_power)) + return -ENODEV; + + if (regulator_is_enabled(exp_power) > 0) { + ret = regulator_get_voltage(exp_power); + if (ret < 0) + return ret; + ret /= 1000; + } + + *eof = 1; + return sprintf(page, "%d\n", ret); +} + +static int exp_power_write(struct file *file, const char __user *buffer, + unsigned long count, void *data) +{ + char buff[32]; + bool enable; + long val; + int ret; + + if (IS_ERR_OR_NULL(exp_power)) + return -ENODEV; + + count = strncpy_from_user(buff, buffer, + count < sizeof(buff) ? count : sizeof(buff) - 1); + buff[count] = 0; + + ret = strict_strtol(buff, 0, &val); + if (ret < 0) + return ret; + + if (val != 0) { + val *= 1000; + ret = regulator_set_voltage(exp_power, val, val); + if (ret < 0) + return ret; + } + enable = !!val; + if (enable == exp_power_proc_enabled) + return count; + if (enable) + ret = regulator_enable(exp_power); + else + ret = regulator_disable(exp_power); + if (ret < 0) + return ret; + + exp_power_proc_enabled = enable; + return count; +} static int __init proc_pandora_init(void) { - struct proc_dir_entry *ret; + struct proc_dir_entry *root, *ret; - ret = proc_mkdir("pandora", NULL); - if (!ret) + /* HACK: create it here, so that others don't need to bother */ + root = proc_mkdir("pandora", NULL); + if (root == NULL) return -ENOMEM; + + ret = create_proc_entry("always_enable_5v", S_IWUSR | S_IRUGO, root); + if (ret != NULL) { + ret->read_proc = v5v_enable_read; + ret->write_proc = v5v_enable_write; + } + + ret = create_proc_entry("exp_power_mv", S_IWUSR | S_IRUGO, root); + if (ret != NULL) { + ret->read_proc = exp_power_read; + ret->write_proc = exp_power_write; + } + return 0; } fs_initcall(proc_pandora_init); -- 2.39.5