pandora: add some hacky controls for expansion and 5v supplies
authorGrazvydas Ignotas <notasas@gmail.com>
Sun, 22 May 2016 22:12:02 +0000 (01:12 +0300)
committerGrazvydas Ignotas <notasas@gmail.com>
Sun, 3 Jul 2016 00:23:25 +0000 (03:23 +0300)
arch/arm/mach-omap2/board-omap3pandora.c

index b9ac6b7..397d46a 100644 (file)
@@ -939,6 +939,11 @@ static struct omap_board_mux board_mux[] __initdata = {
 #endif
 
 static struct regulator *lid_switch_power;
 #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)
 
 #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 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);
 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;
 }
 
        return 0;
 }
@@ -1019,17 +1067,134 @@ static void __init omap3pandora_init(void)
        omap_mux_init_signal("sdrc_cke1", OMAP_PIN_OUTPUT);
 }
 
        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 <linux/proc_fs.h>
 #ifdef CONFIG_PROC_FS
 #include <linux/proc_fs.h>
+#include <linux/uaccess.h>
+
+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)
 {
 
 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;
                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);
        return 0;
 }
 fs_initcall(proc_pandora_init);