| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * Support for the OLPC DCON and OLPC EC access |
|---|
| 3 | 4 | * |
|---|
| 4 | 5 | * Copyright © 2006 Advanced Micro Devices, Inc. |
|---|
| 5 | 6 | * Copyright © 2007-2008 Andres Salomon <dilinger@debian.org> |
|---|
| 6 | | - * |
|---|
| 7 | | - * This program is free software; you can redistribute it and/or modify |
|---|
| 8 | | - * it under the terms of the GNU General Public License as published by |
|---|
| 9 | | - * the Free Software Foundation; either version 2 of the License, or |
|---|
| 10 | | - * (at your option) any later version. |
|---|
| 11 | 7 | */ |
|---|
| 12 | 8 | |
|---|
| 13 | 9 | #include <linux/kernel.h> |
|---|
| .. | .. |
|---|
| 29 | 25 | |
|---|
| 30 | 26 | struct olpc_platform_t olpc_platform_info; |
|---|
| 31 | 27 | EXPORT_SYMBOL_GPL(olpc_platform_info); |
|---|
| 32 | | - |
|---|
| 33 | | -/* EC event mask to be applied during suspend (defining wakeup sources). */ |
|---|
| 34 | | -static u16 ec_wakeup_mask; |
|---|
| 35 | 28 | |
|---|
| 36 | 29 | /* what the timeout *should* be (in ms) */ |
|---|
| 37 | 30 | #define EC_BASE_TIMEOUT 20 |
|---|
| .. | .. |
|---|
| 186 | 179 | return ret; |
|---|
| 187 | 180 | } |
|---|
| 188 | 181 | |
|---|
| 189 | | -void olpc_ec_wakeup_set(u16 value) |
|---|
| 190 | | -{ |
|---|
| 191 | | - ec_wakeup_mask |= value; |
|---|
| 192 | | -} |
|---|
| 193 | | -EXPORT_SYMBOL_GPL(olpc_ec_wakeup_set); |
|---|
| 194 | | - |
|---|
| 195 | | -void olpc_ec_wakeup_clear(u16 value) |
|---|
| 196 | | -{ |
|---|
| 197 | | - ec_wakeup_mask &= ~value; |
|---|
| 198 | | -} |
|---|
| 199 | | -EXPORT_SYMBOL_GPL(olpc_ec_wakeup_clear); |
|---|
| 200 | | - |
|---|
| 201 | | -/* |
|---|
| 202 | | - * Returns true if the compile and runtime configurations allow for EC events |
|---|
| 203 | | - * to wake the system. |
|---|
| 204 | | - */ |
|---|
| 205 | | -bool olpc_ec_wakeup_available(void) |
|---|
| 206 | | -{ |
|---|
| 207 | | - if (!machine_is_olpc()) |
|---|
| 208 | | - return false; |
|---|
| 209 | | - |
|---|
| 210 | | - /* |
|---|
| 211 | | - * XO-1 EC wakeups are available when olpc-xo1-sci driver is |
|---|
| 212 | | - * compiled in |
|---|
| 213 | | - */ |
|---|
| 214 | | -#ifdef CONFIG_OLPC_XO1_SCI |
|---|
| 215 | | - if (olpc_platform_info.boardrev < olpc_board_pre(0xd0)) /* XO-1 */ |
|---|
| 216 | | - return true; |
|---|
| 217 | | -#endif |
|---|
| 218 | | - |
|---|
| 219 | | - /* |
|---|
| 220 | | - * XO-1.5 EC wakeups are available when olpc-xo15-sci driver is |
|---|
| 221 | | - * compiled in |
|---|
| 222 | | - */ |
|---|
| 223 | | -#ifdef CONFIG_OLPC_XO15_SCI |
|---|
| 224 | | - if (olpc_platform_info.boardrev >= olpc_board_pre(0xd0)) /* XO-1.5 */ |
|---|
| 225 | | - return true; |
|---|
| 226 | | -#endif |
|---|
| 227 | | - |
|---|
| 228 | | - return false; |
|---|
| 229 | | -} |
|---|
| 230 | | -EXPORT_SYMBOL_GPL(olpc_ec_wakeup_available); |
|---|
| 231 | | - |
|---|
| 232 | | -int olpc_ec_mask_write(u16 bits) |
|---|
| 233 | | -{ |
|---|
| 234 | | - if (olpc_platform_info.flags & OLPC_F_EC_WIDE_SCI) { |
|---|
| 235 | | - __be16 ec_word = cpu_to_be16(bits); |
|---|
| 236 | | - return olpc_ec_cmd(EC_WRITE_EXT_SCI_MASK, (void *) &ec_word, 2, |
|---|
| 237 | | - NULL, 0); |
|---|
| 238 | | - } else { |
|---|
| 239 | | - unsigned char ec_byte = bits & 0xff; |
|---|
| 240 | | - return olpc_ec_cmd(EC_WRITE_SCI_MASK, &ec_byte, 1, NULL, 0); |
|---|
| 241 | | - } |
|---|
| 242 | | -} |
|---|
| 243 | | -EXPORT_SYMBOL_GPL(olpc_ec_mask_write); |
|---|
| 244 | | - |
|---|
| 245 | | -int olpc_ec_sci_query(u16 *sci_value) |
|---|
| 246 | | -{ |
|---|
| 247 | | - int ret; |
|---|
| 248 | | - |
|---|
| 249 | | - if (olpc_platform_info.flags & OLPC_F_EC_WIDE_SCI) { |
|---|
| 250 | | - __be16 ec_word; |
|---|
| 251 | | - ret = olpc_ec_cmd(EC_EXT_SCI_QUERY, |
|---|
| 252 | | - NULL, 0, (void *) &ec_word, 2); |
|---|
| 253 | | - if (ret == 0) |
|---|
| 254 | | - *sci_value = be16_to_cpu(ec_word); |
|---|
| 255 | | - } else { |
|---|
| 256 | | - unsigned char ec_byte; |
|---|
| 257 | | - ret = olpc_ec_cmd(EC_SCI_QUERY, NULL, 0, &ec_byte, 1); |
|---|
| 258 | | - if (ret == 0) |
|---|
| 259 | | - *sci_value = ec_byte; |
|---|
| 260 | | - } |
|---|
| 261 | | - |
|---|
| 262 | | - return ret; |
|---|
| 263 | | -} |
|---|
| 264 | | -EXPORT_SYMBOL_GPL(olpc_ec_sci_query); |
|---|
| 265 | | - |
|---|
| 266 | 182 | static bool __init check_ofw_architecture(struct device_node *root) |
|---|
| 267 | 183 | { |
|---|
| 268 | 184 | const char *olpc_arch; |
|---|
| .. | .. |
|---|
| 296 | 212 | if (success) { |
|---|
| 297 | 213 | olpc_platform_info.boardrev = get_board_revision(root); |
|---|
| 298 | 214 | olpc_platform_info.flags |= OLPC_F_PRESENT; |
|---|
| 215 | + |
|---|
| 216 | + pr_info("OLPC board revision %s%X\n", |
|---|
| 217 | + ((olpc_platform_info.boardrev & 0xf) < 8) ? "pre" : "", |
|---|
| 218 | + olpc_platform_info.boardrev >> 4); |
|---|
| 299 | 219 | } |
|---|
| 300 | 220 | |
|---|
| 301 | 221 | of_node_put(root); |
|---|
| .. | .. |
|---|
| 315 | 235 | return PTR_ERR_OR_ZERO(pdev); |
|---|
| 316 | 236 | } |
|---|
| 317 | 237 | |
|---|
| 318 | | -static int olpc_xo1_ec_probe(struct platform_device *pdev) |
|---|
| 319 | | -{ |
|---|
| 320 | | - /* get the EC revision */ |
|---|
| 321 | | - olpc_ec_cmd(EC_FIRMWARE_REV, NULL, 0, |
|---|
| 322 | | - (unsigned char *) &olpc_platform_info.ecver, 1); |
|---|
| 323 | | - |
|---|
| 324 | | - /* EC version 0x5f adds support for wide SCI mask */ |
|---|
| 325 | | - if (olpc_platform_info.ecver >= 0x5f) |
|---|
| 326 | | - olpc_platform_info.flags |= OLPC_F_EC_WIDE_SCI; |
|---|
| 327 | | - |
|---|
| 328 | | - pr_info("OLPC board revision %s%X (EC=%x)\n", |
|---|
| 329 | | - ((olpc_platform_info.boardrev & 0xf) < 8) ? "pre" : "", |
|---|
| 330 | | - olpc_platform_info.boardrev >> 4, |
|---|
| 331 | | - olpc_platform_info.ecver); |
|---|
| 332 | | - |
|---|
| 333 | | - return 0; |
|---|
| 334 | | -} |
|---|
| 335 | 238 | static int olpc_xo1_ec_suspend(struct platform_device *pdev) |
|---|
| 336 | 239 | { |
|---|
| 337 | | - olpc_ec_mask_write(ec_wakeup_mask); |
|---|
| 338 | | - |
|---|
| 339 | 240 | /* |
|---|
| 340 | 241 | * Squelch SCIs while suspended. This is a fix for |
|---|
| 341 | 242 | * <http://dev.laptop.org/ticket/1835>. |
|---|
| .. | .. |
|---|
| 359 | 260 | } |
|---|
| 360 | 261 | |
|---|
| 361 | 262 | static struct olpc_ec_driver ec_xo1_driver = { |
|---|
| 362 | | - .probe = olpc_xo1_ec_probe, |
|---|
| 363 | 263 | .suspend = olpc_xo1_ec_suspend, |
|---|
| 364 | 264 | .resume = olpc_xo1_ec_resume, |
|---|
| 365 | 265 | .ec_cmd = olpc_xo1_ec_cmd, |
|---|
| 266 | +#ifdef CONFIG_OLPC_XO1_SCI |
|---|
| 267 | + /* |
|---|
| 268 | + * XO-1 EC wakeups are available when olpc-xo1-sci driver is |
|---|
| 269 | + * compiled in |
|---|
| 270 | + */ |
|---|
| 271 | + .wakeup_available = true, |
|---|
| 272 | +#endif |
|---|
| 366 | 273 | }; |
|---|
| 367 | 274 | |
|---|
| 368 | 275 | static struct olpc_ec_driver ec_xo1_5_driver = { |
|---|
| 369 | | - .probe = olpc_xo1_ec_probe, |
|---|
| 370 | 276 | .ec_cmd = olpc_xo1_ec_cmd, |
|---|
| 277 | +#ifdef CONFIG_OLPC_XO15_SCI |
|---|
| 278 | + /* |
|---|
| 279 | + * XO-1.5 EC wakeups are available when olpc-xo15-sci driver is |
|---|
| 280 | + * compiled in |
|---|
| 281 | + */ |
|---|
| 282 | + .wakeup_available = true, |
|---|
| 283 | +#endif |
|---|
| 371 | 284 | }; |
|---|
| 372 | 285 | |
|---|
| 373 | 286 | static int __init olpc_init(void) |
|---|