Platform: OLPC: Move EC-specific functionality out from x86
authorLubomir Rintel <lkundrak@v3.sk>
Mon, 13 May 2019 07:56:34 +0000 (09:56 +0200)
committerAndy Shevchenko <andriy.shevchenko@linux.intel.com>
Mon, 20 May 2019 14:27:08 +0000 (17:27 +0300)
Move the olpc-ec driver away from the X86 OLPC platform so that it could be
used by the ARM based laptops too. Notably, the driver for the OLPC battery,
which is also used on the ARM models, builds on this driver's interface.

It is actually plaform independent: the OLPC EC commands with their argument
and responses are mostly the same despite the delivery mechanism is
different.

Signed-off-by: Lubomir Rintel <lkundrak@v3.sk>
Acked-by: Pavel Machek <pavel@ucw.cz>
Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
arch/x86/include/asm/olpc.h
arch/x86/platform/olpc/olpc.c
drivers/platform/olpc/olpc-ec.c
drivers/power/supply/olpc_battery.c
include/linux/olpc-ec.h

index c2bf1de..6fe7628 100644 (file)
@@ -9,12 +9,10 @@
 struct olpc_platform_t {
        int flags;
        uint32_t boardrev;
-       int ecver;
 };
 
 #define OLPC_F_PRESENT         0x01
 #define OLPC_F_DCON            0x02
-#define OLPC_F_EC_WIDE_SCI     0x04
 
 #ifdef CONFIG_OLPC
 
@@ -64,13 +62,6 @@ static inline int olpc_board_at_least(uint32_t rev)
        return olpc_platform_info.boardrev >= rev;
 }
 
-extern void olpc_ec_wakeup_set(u16 value);
-extern void olpc_ec_wakeup_clear(u16 value);
-extern bool olpc_ec_wakeup_available(void);
-
-extern int olpc_ec_mask_write(u16 bits);
-extern int olpc_ec_sci_query(u16 *sci_value);
-
 #else
 
 static inline int machine_is_olpc(void)
@@ -83,14 +74,6 @@ static inline int olpc_has_dcon(void)
        return 0;
 }
 
-static inline void olpc_ec_wakeup_set(u16 value) { }
-static inline void olpc_ec_wakeup_clear(u16 value) { }
-
-static inline bool olpc_ec_wakeup_available(void)
-{
-       return false;
-}
-
 #endif
 
 #ifdef CONFIG_OLPC_XO1_PM
@@ -101,20 +84,6 @@ extern void olpc_xo1_pm_wakeup_clear(u16 value);
 
 extern int pci_olpc_init(void);
 
-/* SCI source values */
-
-#define EC_SCI_SRC_EMPTY       0x00
-#define EC_SCI_SRC_GAME                0x01
-#define EC_SCI_SRC_BATTERY     0x02
-#define EC_SCI_SRC_BATSOC      0x04
-#define EC_SCI_SRC_BATERR      0x08
-#define EC_SCI_SRC_EBOOK       0x10    /* XO-1 only */
-#define EC_SCI_SRC_WLAN                0x20    /* XO-1 only */
-#define EC_SCI_SRC_ACPWR       0x40
-#define EC_SCI_SRC_BATCRIT     0x80
-#define EC_SCI_SRC_GPWAKE      0x100   /* XO-1.5 only */
-#define EC_SCI_SRC_ALL         0x1FF
-
 /* GPIO assignments */
 
 #define OLPC_GPIO_MIC_AC       1
index f0e920f..c6c62b4 100644 (file)
@@ -30,9 +30,6 @@
 struct olpc_platform_t olpc_platform_info;
 EXPORT_SYMBOL_GPL(olpc_platform_info);
 
-/* EC event mask to be applied during suspend (defining wakeup sources). */
-static u16 ec_wakeup_mask;
-
 /* what the timeout *should* be (in ms) */
 #define EC_BASE_TIMEOUT 20
 
@@ -186,83 +183,6 @@ err:
        return ret;
 }
 
-void olpc_ec_wakeup_set(u16 value)
-{
-       ec_wakeup_mask |= value;
-}
-EXPORT_SYMBOL_GPL(olpc_ec_wakeup_set);
-
-void olpc_ec_wakeup_clear(u16 value)
-{
-       ec_wakeup_mask &= ~value;
-}
-EXPORT_SYMBOL_GPL(olpc_ec_wakeup_clear);
-
-/*
- * Returns true if the compile and runtime configurations allow for EC events
- * to wake the system.
- */
-bool olpc_ec_wakeup_available(void)
-{
-       if (!machine_is_olpc())
-               return false;
-
-       /*
-        * XO-1 EC wakeups are available when olpc-xo1-sci driver is
-        * compiled in
-        */
-#ifdef CONFIG_OLPC_XO1_SCI
-       if (olpc_platform_info.boardrev < olpc_board_pre(0xd0)) /* XO-1 */
-               return true;
-#endif
-
-       /*
-        * XO-1.5 EC wakeups are available when olpc-xo15-sci driver is
-        * compiled in
-        */
-#ifdef CONFIG_OLPC_XO15_SCI
-       if (olpc_platform_info.boardrev >= olpc_board_pre(0xd0)) /* XO-1.5 */
-               return true;
-#endif
-
-       return false;
-}
-EXPORT_SYMBOL_GPL(olpc_ec_wakeup_available);
-
-int olpc_ec_mask_write(u16 bits)
-{
-       if (olpc_platform_info.flags & OLPC_F_EC_WIDE_SCI) {
-               __be16 ec_word = cpu_to_be16(bits);
-               return olpc_ec_cmd(EC_WRITE_EXT_SCI_MASK, (void *) &ec_word, 2,
-                                  NULL, 0);
-       } else {
-               unsigned char ec_byte = bits & 0xff;
-               return olpc_ec_cmd(EC_WRITE_SCI_MASK, &ec_byte, 1, NULL, 0);
-       }
-}
-EXPORT_SYMBOL_GPL(olpc_ec_mask_write);
-
-int olpc_ec_sci_query(u16 *sci_value)
-{
-       int ret;
-
-       if (olpc_platform_info.flags & OLPC_F_EC_WIDE_SCI) {
-               __be16 ec_word;
-               ret = olpc_ec_cmd(EC_EXT_SCI_QUERY,
-                       NULL, 0, (void *) &ec_word, 2);
-               if (ret == 0)
-                       *sci_value = be16_to_cpu(ec_word);
-       } else {
-               unsigned char ec_byte;
-               ret = olpc_ec_cmd(EC_SCI_QUERY, NULL, 0, &ec_byte, 1);
-               if (ret == 0)
-                       *sci_value = ec_byte;
-       }
-
-       return ret;
-}
-EXPORT_SYMBOL_GPL(olpc_ec_sci_query);
-
 static bool __init check_ofw_architecture(struct device_node *root)
 {
        const char *olpc_arch;
@@ -296,6 +216,10 @@ static bool __init platform_detect(void)
        if (success) {
                olpc_platform_info.boardrev = get_board_revision(root);
                olpc_platform_info.flags |= OLPC_F_PRESENT;
+
+               pr_info("OLPC board revision %s%X\n",
+                       ((olpc_platform_info.boardrev & 0xf) < 8) ? "pre" : "",
+                       olpc_platform_info.boardrev >> 4);
        }
 
        of_node_put(root);
@@ -315,27 +239,8 @@ static int __init add_xo1_platform_devices(void)
        return PTR_ERR_OR_ZERO(pdev);
 }
 
-static int olpc_xo1_ec_probe(struct platform_device *pdev)
-{
-       /* get the EC revision */
-       olpc_ec_cmd(EC_FIRMWARE_REV, NULL, 0,
-                       (unsigned char *) &olpc_platform_info.ecver, 1);
-
-       /* EC version 0x5f adds support for wide SCI mask */
-       if (olpc_platform_info.ecver >= 0x5f)
-               olpc_platform_info.flags |= OLPC_F_EC_WIDE_SCI;
-
-       pr_info("OLPC board revision %s%X (EC=%x)\n",
-                       ((olpc_platform_info.boardrev & 0xf) < 8) ? "pre" : "",
-                       olpc_platform_info.boardrev >> 4,
-                       olpc_platform_info.ecver);
-
-       return 0;
-}
 static int olpc_xo1_ec_suspend(struct platform_device *pdev)
 {
-       olpc_ec_mask_write(ec_wakeup_mask);
-
        /*
         * Squelch SCIs while suspended.  This is a fix for
         * <http://dev.laptop.org/ticket/1835>.
@@ -359,15 +264,27 @@ static int olpc_xo1_ec_resume(struct platform_device *pdev)
 }
 
 static struct olpc_ec_driver ec_xo1_driver = {
-       .probe = olpc_xo1_ec_probe,
        .suspend = olpc_xo1_ec_suspend,
        .resume = olpc_xo1_ec_resume,
        .ec_cmd = olpc_xo1_ec_cmd,
+#ifdef CONFIG_OLPC_XO1_SCI
+       /*
+        * XO-1 EC wakeups are available when olpc-xo1-sci driver is
+        * compiled in
+        */
+       .wakeup_available = true,
+#endif
 };
 
 static struct olpc_ec_driver ec_xo1_5_driver = {
-       .probe = olpc_xo1_ec_probe,
        .ec_cmd = olpc_xo1_ec_cmd,
+#ifdef CONFIG_OLPC_XO1_5_SCI
+       /*
+        * XO-1.5 EC wakeups are available when olpc-xo15-sci driver is
+        * compiled in
+        */
+       .wakeup_available = true,
+#endif
 };
 
 static int __init olpc_init(void)
index 981955d..2a64745 100644 (file)
@@ -32,6 +32,7 @@ struct ec_cmd_desc {
 
 struct olpc_ec_priv {
        struct olpc_ec_driver *drv;
+       u8 version;
        struct work_struct worker;
        struct mutex cmd_lock;
 
@@ -41,6 +42,12 @@ struct olpc_ec_priv {
 
        struct dentry *dbgfs_dir;
 
+       /*
+        * EC event mask to be applied during suspend (defining wakeup
+        * sources).
+        */
+       u16 ec_wakeup_mask;
+
        /*
         * Running an EC command while suspending means we don't always finish
         * the command before the machine suspends.  This means that the EC
@@ -149,6 +156,88 @@ int olpc_ec_cmd(u8 cmd, u8 *inbuf, size_t inlen, u8 *outbuf, size_t outlen)
 }
 EXPORT_SYMBOL_GPL(olpc_ec_cmd);
 
+void olpc_ec_wakeup_set(u16 value)
+{
+       struct olpc_ec_priv *ec = ec_priv;
+
+       if (WARN_ON(!ec))
+               return;
+
+       ec->ec_wakeup_mask |= value;
+}
+EXPORT_SYMBOL_GPL(olpc_ec_wakeup_set);
+
+void olpc_ec_wakeup_clear(u16 value)
+{
+       struct olpc_ec_priv *ec = ec_priv;
+
+       if (WARN_ON(!ec))
+               return;
+
+       ec->ec_wakeup_mask &= ~value;
+}
+EXPORT_SYMBOL_GPL(olpc_ec_wakeup_clear);
+
+int olpc_ec_mask_write(u16 bits)
+{
+       struct olpc_ec_priv *ec = ec_priv;
+
+       if (WARN_ON(!ec))
+               return -ENODEV;
+
+       /* EC version 0x5f adds support for wide SCI mask */
+       if (ec->version >= 0x5f) {
+               __be16 ec_word = cpu_to_be16(bits);
+
+               return olpc_ec_cmd(EC_WRITE_EXT_SCI_MASK, (void *)&ec_word, 2, NULL, 0);
+       } else {
+               u8 ec_byte = bits & 0xff;
+
+               return olpc_ec_cmd(EC_WRITE_SCI_MASK, &ec_byte, 1, NULL, 0);
+       }
+}
+EXPORT_SYMBOL_GPL(olpc_ec_mask_write);
+
+/*
+ * Returns true if the compile and runtime configurations allow for EC events
+ * to wake the system.
+ */
+bool olpc_ec_wakeup_available(void)
+{
+       if (WARN_ON(!ec_driver))
+               return false;
+
+       return ec_driver->wakeup_available;
+}
+EXPORT_SYMBOL_GPL(olpc_ec_wakeup_available);
+
+int olpc_ec_sci_query(u16 *sci_value)
+{
+       struct olpc_ec_priv *ec = ec_priv;
+       int ret;
+
+       if (WARN_ON(!ec))
+               return -ENODEV;
+
+       /* EC version 0x5f adds support for wide SCI mask */
+       if (ec->version >= 0x5f) {
+               __be16 ec_word;
+
+               ret = olpc_ec_cmd(EC_EXT_SCI_QUERY, NULL, 0, (void *)&ec_word, 2);
+               if (ret == 0)
+                       *sci_value = be16_to_cpu(ec_word);
+       } else {
+               u8 ec_byte;
+
+               ret = olpc_ec_cmd(EC_SCI_QUERY, NULL, 0, &ec_byte, 1);
+               if (ret == 0)
+                       *sci_value = ec_byte;
+       }
+
+       return ret;
+}
+EXPORT_SYMBOL_GPL(olpc_ec_sci_query);
+
 #ifdef CONFIG_DEBUG_FS
 
 /*
@@ -276,14 +365,16 @@ static int olpc_ec_probe(struct platform_device *pdev)
        ec_priv = ec;
        platform_set_drvdata(pdev, ec);
 
-       err = ec_driver->probe ? ec_driver->probe(pdev) : 0;
+       /* get the EC revision */
+       err = olpc_ec_cmd(EC_FIRMWARE_REV, NULL, 0, &ec->version, 1);
        if (err) {
                ec_priv = NULL;
                kfree(ec);
-       } else {
-               ec->dbgfs_dir = olpc_ec_setup_debugfs();
+               return err;
        }
 
+       ec->dbgfs_dir = olpc_ec_setup_debugfs();
+
        return err;
 }
 
@@ -293,6 +384,8 @@ static int olpc_ec_suspend(struct device *dev)
        struct olpc_ec_priv *ec = platform_get_drvdata(pdev);
        int err = 0;
 
+       olpc_ec_mask_write(ec->ec_wakeup_mask);
+
        if (ec_driver->suspend)
                err = ec_driver->suspend(pdev);
        if (!err)
index 7720e4c..066ec9a 100644 (file)
@@ -20,7 +20,6 @@
 #include <linux/jiffies.h>
 #include <linux/sched.h>
 #include <linux/olpc-ec.h>
-#include <asm/olpc.h>
 
 
 #define EC_BAT_VOLTAGE 0x10    /* uint16_t,    *9.76/32,    mV   */
index 79bdc63..7fa3d27 100644 (file)
 #define EC_SCI_QUERY                   0x84
 #define EC_EXT_SCI_QUERY               0x85
 
+/* SCI source values */
+#define EC_SCI_SRC_EMPTY        0x00
+#define EC_SCI_SRC_GAME         0x01
+#define EC_SCI_SRC_BATTERY      0x02
+#define EC_SCI_SRC_BATSOC       0x04
+#define EC_SCI_SRC_BATERR       0x08
+#define EC_SCI_SRC_EBOOK        0x10    /* XO-1 only */
+#define EC_SCI_SRC_WLAN         0x20    /* XO-1 only */
+#define EC_SCI_SRC_ACPWR        0x40
+#define EC_SCI_SRC_BATCRIT      0x80
+#define EC_SCI_SRC_GPWAKE       0x100   /* XO-1.5 only */
+#define EC_SCI_SRC_ALL          0x1FF
+
 struct platform_device;
 
 struct olpc_ec_driver {
-       int (*probe)(struct platform_device *);
        int (*suspend)(struct platform_device *);
        int (*resume)(struct platform_device *);
 
        int (*ec_cmd)(u8, u8 *, size_t, u8 *, size_t, void *);
+
+       bool wakeup_available;
 };
 
 #ifdef CONFIG_OLPC
@@ -33,11 +47,27 @@ extern void olpc_ec_driver_register(struct olpc_ec_driver *drv, void *arg);
 extern int olpc_ec_cmd(u8 cmd, u8 *inbuf, size_t inlen, u8 *outbuf,
                size_t outlen);
 
+extern void olpc_ec_wakeup_set(u16 value);
+extern void olpc_ec_wakeup_clear(u16 value);
+
+extern int olpc_ec_mask_write(u16 bits);
+extern int olpc_ec_sci_query(u16 *sci_value);
+
+extern bool olpc_ec_wakeup_available(void);
+
 #else
 
 static inline int olpc_ec_cmd(u8 cmd, u8 *inbuf, size_t inlen, u8 *outbuf,
                size_t outlen) { return -ENODEV; }
 
+static inline void olpc_ec_wakeup_set(u16 value) { }
+static inline void olpc_ec_wakeup_clear(u16 value) { }
+
+static inline bool olpc_ec_wakeup_available(void)
+{
+       return false;
+}
+
 #endif /* CONFIG_OLPC */
 
 #endif /* _LINUX_OLPC_EC_H */