Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Platform: OLPC: Move EC-specific functionality out from x86

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>

authored by

Lubomir Rintel and committed by
Andy Shevchenko
ec9964b4 2dc78630

+145 -137
-31
arch/x86/include/asm/olpc.h
··· 9 9 struct olpc_platform_t { 10 10 int flags; 11 11 uint32_t boardrev; 12 - int ecver; 13 12 }; 14 13 15 14 #define OLPC_F_PRESENT 0x01 16 15 #define OLPC_F_DCON 0x02 17 - #define OLPC_F_EC_WIDE_SCI 0x04 18 16 19 17 #ifdef CONFIG_OLPC 20 18 ··· 62 64 return olpc_platform_info.boardrev >= rev; 63 65 } 64 66 65 - extern void olpc_ec_wakeup_set(u16 value); 66 - extern void olpc_ec_wakeup_clear(u16 value); 67 - extern bool olpc_ec_wakeup_available(void); 68 - 69 - extern int olpc_ec_mask_write(u16 bits); 70 - extern int olpc_ec_sci_query(u16 *sci_value); 71 - 72 67 #else 73 68 74 69 static inline int machine_is_olpc(void) ··· 74 83 return 0; 75 84 } 76 85 77 - static inline void olpc_ec_wakeup_set(u16 value) { } 78 - static inline void olpc_ec_wakeup_clear(u16 value) { } 79 - 80 - static inline bool olpc_ec_wakeup_available(void) 81 - { 82 - return false; 83 - } 84 - 85 86 #endif 86 87 87 88 #ifdef CONFIG_OLPC_XO1_PM ··· 83 100 #endif 84 101 85 102 extern int pci_olpc_init(void); 86 - 87 - /* SCI source values */ 88 - 89 - #define EC_SCI_SRC_EMPTY 0x00 90 - #define EC_SCI_SRC_GAME 0x01 91 - #define EC_SCI_SRC_BATTERY 0x02 92 - #define EC_SCI_SRC_BATSOC 0x04 93 - #define EC_SCI_SRC_BATERR 0x08 94 - #define EC_SCI_SRC_EBOOK 0x10 /* XO-1 only */ 95 - #define EC_SCI_SRC_WLAN 0x20 /* XO-1 only */ 96 - #define EC_SCI_SRC_ACPWR 0x40 97 - #define EC_SCI_SRC_BATCRIT 0x80 98 - #define EC_SCI_SRC_GPWAKE 0x100 /* XO-1.5 only */ 99 - #define EC_SCI_SRC_ALL 0x1FF 100 103 101 104 /* GPIO assignments */ 102 105
+18 -101
arch/x86/platform/olpc/olpc.c
··· 30 30 struct olpc_platform_t olpc_platform_info; 31 31 EXPORT_SYMBOL_GPL(olpc_platform_info); 32 32 33 - /* EC event mask to be applied during suspend (defining wakeup sources). */ 34 - static u16 ec_wakeup_mask; 35 - 36 33 /* what the timeout *should* be (in ms) */ 37 34 #define EC_BASE_TIMEOUT 20 38 35 ··· 183 186 return ret; 184 187 } 185 188 186 - void olpc_ec_wakeup_set(u16 value) 187 - { 188 - ec_wakeup_mask |= value; 189 - } 190 - EXPORT_SYMBOL_GPL(olpc_ec_wakeup_set); 191 - 192 - void olpc_ec_wakeup_clear(u16 value) 193 - { 194 - ec_wakeup_mask &= ~value; 195 - } 196 - EXPORT_SYMBOL_GPL(olpc_ec_wakeup_clear); 197 - 198 - /* 199 - * Returns true if the compile and runtime configurations allow for EC events 200 - * to wake the system. 201 - */ 202 - bool olpc_ec_wakeup_available(void) 203 - { 204 - if (!machine_is_olpc()) 205 - return false; 206 - 207 - /* 208 - * XO-1 EC wakeups are available when olpc-xo1-sci driver is 209 - * compiled in 210 - */ 211 - #ifdef CONFIG_OLPC_XO1_SCI 212 - if (olpc_platform_info.boardrev < olpc_board_pre(0xd0)) /* XO-1 */ 213 - return true; 214 - #endif 215 - 216 - /* 217 - * XO-1.5 EC wakeups are available when olpc-xo15-sci driver is 218 - * compiled in 219 - */ 220 - #ifdef CONFIG_OLPC_XO15_SCI 221 - if (olpc_platform_info.boardrev >= olpc_board_pre(0xd0)) /* XO-1.5 */ 222 - return true; 223 - #endif 224 - 225 - return false; 226 - } 227 - EXPORT_SYMBOL_GPL(olpc_ec_wakeup_available); 228 - 229 - int olpc_ec_mask_write(u16 bits) 230 - { 231 - if (olpc_platform_info.flags & OLPC_F_EC_WIDE_SCI) { 232 - __be16 ec_word = cpu_to_be16(bits); 233 - return olpc_ec_cmd(EC_WRITE_EXT_SCI_MASK, (void *) &ec_word, 2, 234 - NULL, 0); 235 - } else { 236 - unsigned char ec_byte = bits & 0xff; 237 - return olpc_ec_cmd(EC_WRITE_SCI_MASK, &ec_byte, 1, NULL, 0); 238 - } 239 - } 240 - EXPORT_SYMBOL_GPL(olpc_ec_mask_write); 241 - 242 - int olpc_ec_sci_query(u16 *sci_value) 243 - { 244 - int ret; 245 - 246 - if (olpc_platform_info.flags & OLPC_F_EC_WIDE_SCI) { 247 - __be16 ec_word; 248 - ret = olpc_ec_cmd(EC_EXT_SCI_QUERY, 249 - NULL, 0, (void *) &ec_word, 2); 250 - if (ret == 0) 251 - *sci_value = be16_to_cpu(ec_word); 252 - } else { 253 - unsigned char ec_byte; 254 - ret = olpc_ec_cmd(EC_SCI_QUERY, NULL, 0, &ec_byte, 1); 255 - if (ret == 0) 256 - *sci_value = ec_byte; 257 - } 258 - 259 - return ret; 260 - } 261 - EXPORT_SYMBOL_GPL(olpc_ec_sci_query); 262 - 263 189 static bool __init check_ofw_architecture(struct device_node *root) 264 190 { 265 191 const char *olpc_arch; ··· 216 296 if (success) { 217 297 olpc_platform_info.boardrev = get_board_revision(root); 218 298 olpc_platform_info.flags |= OLPC_F_PRESENT; 299 + 300 + pr_info("OLPC board revision %s%X\n", 301 + ((olpc_platform_info.boardrev & 0xf) < 8) ? "pre" : "", 302 + olpc_platform_info.boardrev >> 4); 219 303 } 220 304 221 305 of_node_put(root); ··· 239 315 return PTR_ERR_OR_ZERO(pdev); 240 316 } 241 317 242 - static int olpc_xo1_ec_probe(struct platform_device *pdev) 243 - { 244 - /* get the EC revision */ 245 - olpc_ec_cmd(EC_FIRMWARE_REV, NULL, 0, 246 - (unsigned char *) &olpc_platform_info.ecver, 1); 247 - 248 - /* EC version 0x5f adds support for wide SCI mask */ 249 - if (olpc_platform_info.ecver >= 0x5f) 250 - olpc_platform_info.flags |= OLPC_F_EC_WIDE_SCI; 251 - 252 - pr_info("OLPC board revision %s%X (EC=%x)\n", 253 - ((olpc_platform_info.boardrev & 0xf) < 8) ? "pre" : "", 254 - olpc_platform_info.boardrev >> 4, 255 - olpc_platform_info.ecver); 256 - 257 - return 0; 258 - } 259 318 static int olpc_xo1_ec_suspend(struct platform_device *pdev) 260 319 { 261 - olpc_ec_mask_write(ec_wakeup_mask); 262 - 263 320 /* 264 321 * Squelch SCIs while suspended. This is a fix for 265 322 * <http://dev.laptop.org/ticket/1835>. ··· 264 359 } 265 360 266 361 static struct olpc_ec_driver ec_xo1_driver = { 267 - .probe = olpc_xo1_ec_probe, 268 362 .suspend = olpc_xo1_ec_suspend, 269 363 .resume = olpc_xo1_ec_resume, 270 364 .ec_cmd = olpc_xo1_ec_cmd, 365 + #ifdef CONFIG_OLPC_XO1_SCI 366 + /* 367 + * XO-1 EC wakeups are available when olpc-xo1-sci driver is 368 + * compiled in 369 + */ 370 + .wakeup_available = true, 371 + #endif 271 372 }; 272 373 273 374 static struct olpc_ec_driver ec_xo1_5_driver = { 274 - .probe = olpc_xo1_ec_probe, 275 375 .ec_cmd = olpc_xo1_ec_cmd, 376 + #ifdef CONFIG_OLPC_XO1_5_SCI 377 + /* 378 + * XO-1.5 EC wakeups are available when olpc-xo15-sci driver is 379 + * compiled in 380 + */ 381 + .wakeup_available = true, 382 + #endif 276 383 }; 277 384 278 385 static int __init olpc_init(void)
+96 -3
drivers/platform/olpc/olpc-ec.c
··· 32 32 33 33 struct olpc_ec_priv { 34 34 struct olpc_ec_driver *drv; 35 + u8 version; 35 36 struct work_struct worker; 36 37 struct mutex cmd_lock; 37 38 ··· 41 40 spinlock_t cmd_q_lock; 42 41 43 42 struct dentry *dbgfs_dir; 43 + 44 + /* 45 + * EC event mask to be applied during suspend (defining wakeup 46 + * sources). 47 + */ 48 + u16 ec_wakeup_mask; 44 49 45 50 /* 46 51 * Running an EC command while suspending means we don't always finish ··· 155 148 return desc.err; 156 149 } 157 150 EXPORT_SYMBOL_GPL(olpc_ec_cmd); 151 + 152 + void olpc_ec_wakeup_set(u16 value) 153 + { 154 + struct olpc_ec_priv *ec = ec_priv; 155 + 156 + if (WARN_ON(!ec)) 157 + return; 158 + 159 + ec->ec_wakeup_mask |= value; 160 + } 161 + EXPORT_SYMBOL_GPL(olpc_ec_wakeup_set); 162 + 163 + void olpc_ec_wakeup_clear(u16 value) 164 + { 165 + struct olpc_ec_priv *ec = ec_priv; 166 + 167 + if (WARN_ON(!ec)) 168 + return; 169 + 170 + ec->ec_wakeup_mask &= ~value; 171 + } 172 + EXPORT_SYMBOL_GPL(olpc_ec_wakeup_clear); 173 + 174 + int olpc_ec_mask_write(u16 bits) 175 + { 176 + struct olpc_ec_priv *ec = ec_priv; 177 + 178 + if (WARN_ON(!ec)) 179 + return -ENODEV; 180 + 181 + /* EC version 0x5f adds support for wide SCI mask */ 182 + if (ec->version >= 0x5f) { 183 + __be16 ec_word = cpu_to_be16(bits); 184 + 185 + return olpc_ec_cmd(EC_WRITE_EXT_SCI_MASK, (void *)&ec_word, 2, NULL, 0); 186 + } else { 187 + u8 ec_byte = bits & 0xff; 188 + 189 + return olpc_ec_cmd(EC_WRITE_SCI_MASK, &ec_byte, 1, NULL, 0); 190 + } 191 + } 192 + EXPORT_SYMBOL_GPL(olpc_ec_mask_write); 193 + 194 + /* 195 + * Returns true if the compile and runtime configurations allow for EC events 196 + * to wake the system. 197 + */ 198 + bool olpc_ec_wakeup_available(void) 199 + { 200 + if (WARN_ON(!ec_driver)) 201 + return false; 202 + 203 + return ec_driver->wakeup_available; 204 + } 205 + EXPORT_SYMBOL_GPL(olpc_ec_wakeup_available); 206 + 207 + int olpc_ec_sci_query(u16 *sci_value) 208 + { 209 + struct olpc_ec_priv *ec = ec_priv; 210 + int ret; 211 + 212 + if (WARN_ON(!ec)) 213 + return -ENODEV; 214 + 215 + /* EC version 0x5f adds support for wide SCI mask */ 216 + if (ec->version >= 0x5f) { 217 + __be16 ec_word; 218 + 219 + ret = olpc_ec_cmd(EC_EXT_SCI_QUERY, NULL, 0, (void *)&ec_word, 2); 220 + if (ret == 0) 221 + *sci_value = be16_to_cpu(ec_word); 222 + } else { 223 + u8 ec_byte; 224 + 225 + ret = olpc_ec_cmd(EC_SCI_QUERY, NULL, 0, &ec_byte, 1); 226 + if (ret == 0) 227 + *sci_value = ec_byte; 228 + } 229 + 230 + return ret; 231 + } 232 + EXPORT_SYMBOL_GPL(olpc_ec_sci_query); 158 233 159 234 #ifdef CONFIG_DEBUG_FS 160 235 ··· 365 276 ec_priv = ec; 366 277 platform_set_drvdata(pdev, ec); 367 278 368 - err = ec_driver->probe ? ec_driver->probe(pdev) : 0; 279 + /* get the EC revision */ 280 + err = olpc_ec_cmd(EC_FIRMWARE_REV, NULL, 0, &ec->version, 1); 369 281 if (err) { 370 282 ec_priv = NULL; 371 283 kfree(ec); 372 - } else { 373 - ec->dbgfs_dir = olpc_ec_setup_debugfs(); 284 + return err; 374 285 } 286 + 287 + ec->dbgfs_dir = olpc_ec_setup_debugfs(); 375 288 376 289 return err; 377 290 } ··· 383 292 struct platform_device *pdev = to_platform_device(dev); 384 293 struct olpc_ec_priv *ec = platform_get_drvdata(pdev); 385 294 int err = 0; 295 + 296 + olpc_ec_mask_write(ec->ec_wakeup_mask); 386 297 387 298 if (ec_driver->suspend) 388 299 err = ec_driver->suspend(pdev);
-1
drivers/power/supply/olpc_battery.c
··· 20 20 #include <linux/jiffies.h> 21 21 #include <linux/sched.h> 22 22 #include <linux/olpc-ec.h> 23 - #include <asm/olpc.h> 24 23 25 24 26 25 #define EC_BAT_VOLTAGE 0x10 /* uint16_t, *9.76/32, mV */
+31 -1
include/linux/olpc-ec.h
··· 16 16 #define EC_SCI_QUERY 0x84 17 17 #define EC_EXT_SCI_QUERY 0x85 18 18 19 + /* SCI source values */ 20 + #define EC_SCI_SRC_EMPTY 0x00 21 + #define EC_SCI_SRC_GAME 0x01 22 + #define EC_SCI_SRC_BATTERY 0x02 23 + #define EC_SCI_SRC_BATSOC 0x04 24 + #define EC_SCI_SRC_BATERR 0x08 25 + #define EC_SCI_SRC_EBOOK 0x10 /* XO-1 only */ 26 + #define EC_SCI_SRC_WLAN 0x20 /* XO-1 only */ 27 + #define EC_SCI_SRC_ACPWR 0x40 28 + #define EC_SCI_SRC_BATCRIT 0x80 29 + #define EC_SCI_SRC_GPWAKE 0x100 /* XO-1.5 only */ 30 + #define EC_SCI_SRC_ALL 0x1FF 31 + 19 32 struct platform_device; 20 33 21 34 struct olpc_ec_driver { 22 - int (*probe)(struct platform_device *); 23 35 int (*suspend)(struct platform_device *); 24 36 int (*resume)(struct platform_device *); 25 37 26 38 int (*ec_cmd)(u8, u8 *, size_t, u8 *, size_t, void *); 39 + 40 + bool wakeup_available; 27 41 }; 28 42 29 43 #ifdef CONFIG_OLPC ··· 47 33 extern int olpc_ec_cmd(u8 cmd, u8 *inbuf, size_t inlen, u8 *outbuf, 48 34 size_t outlen); 49 35 36 + extern void olpc_ec_wakeup_set(u16 value); 37 + extern void olpc_ec_wakeup_clear(u16 value); 38 + 39 + extern int olpc_ec_mask_write(u16 bits); 40 + extern int olpc_ec_sci_query(u16 *sci_value); 41 + 42 + extern bool olpc_ec_wakeup_available(void); 43 + 50 44 #else 51 45 52 46 static inline int olpc_ec_cmd(u8 cmd, u8 *inbuf, size_t inlen, u8 *outbuf, 53 47 size_t outlen) { return -ENODEV; } 48 + 49 + static inline void olpc_ec_wakeup_set(u16 value) { } 50 + static inline void olpc_ec_wakeup_clear(u16 value) { } 51 + 52 + static inline bool olpc_ec_wakeup_available(void) 53 + { 54 + return false; 55 + } 54 56 55 57 #endif /* CONFIG_OLPC */ 56 58