1 /* 2 * pnpacpi -- PnP ACPI driver 3 * 4 * Copyright (c) 2004 Matthieu Castet <castet.matthieu@free.fr> 5 * Copyright (c) 2004 Li Shaohua <shaohua.li@intel.com> 6 * 7 * This program is free software; you can redistribute it and/or modify it 8 * under the terms of the GNU General Public License as published by the 9 * Free Software Foundation; either version 2, or (at your option) any 10 * later version. 11 * 12 * This program is distributed in the hope that it will be useful, but 13 * WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 * General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with this program; if not, write to the Free Software 19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 */ 21 22 #include <linux/export.h> 23 #include <linux/acpi.h> 24 #include <linux/pnp.h> 25 #include <linux/slab.h> 26 #include <linux/mod_devicetable.h> 27 #include <acpi/acpi_bus.h> 28 29 #include "../base.h" 30 #include "pnpacpi.h" 31 32 static int num; 33 34 /* We need only to blacklist devices that have already an acpi driver that 35 * can't use pnp layer. We don't need to blacklist device that are directly 36 * used by the kernel (PCI root, ...), as it is harmless and there were 37 * already present in pnpbios. But there is an exception for devices that 38 * have irqs (PIC, Timer) because we call acpi_register_gsi. 39 * Finally, only devices that have a CRS method need to be in this list. 40 */ 41 static struct acpi_device_id excluded_id_list[] __initdata = { 42 {"PNP0C09", 0}, /* EC */ 43 {"PNP0C0F", 0}, /* Link device */ 44 {"PNP0000", 0}, /* PIC */ 45 {"PNP0100", 0}, /* Timer */ 46 {"", 0}, 47 }; 48 49 static inline int __init is_exclusive_device(struct acpi_device *dev) 50 { 51 return (!acpi_match_device_ids(dev, excluded_id_list)); 52 } 53 54 /* 55 * Compatible Device IDs 56 */ 57 #define TEST_HEX(c) \ 58 if (!(('0' <= (c) && (c) <= '9') || ('A' <= (c) && (c) <= 'F'))) \ 59 return 0 60 #define TEST_ALPHA(c) \ 61 if (!('A' <= (c) && (c) <= 'Z')) \ 62 return 0 63 static int __init ispnpidacpi(const char *id) 64 { 65 TEST_ALPHA(id[0]); 66 TEST_ALPHA(id[1]); 67 TEST_ALPHA(id[2]); 68 TEST_HEX(id[3]); 69 TEST_HEX(id[4]); 70 TEST_HEX(id[5]); 71 TEST_HEX(id[6]); 72 if (id[7] != '\0') 73 return 0; 74 return 1; 75 } 76 77 static int pnpacpi_get_resources(struct pnp_dev *dev) 78 { 79 pnp_dbg(&dev->dev, "get resources\n"); 80 return pnpacpi_parse_allocated_resource(dev); 81 } 82 83 static int pnpacpi_set_resources(struct pnp_dev *dev) 84 { 85 struct acpi_device *acpi_dev; 86 acpi_handle handle; 87 struct acpi_buffer buffer; 88 int ret; 89 90 pnp_dbg(&dev->dev, "set resources\n"); 91 92 handle = DEVICE_ACPI_HANDLE(&dev->dev); 93 if (!handle || ACPI_FAILURE(acpi_bus_get_device(handle, &acpi_dev))) { 94 dev_dbg(&dev->dev, "ACPI device not found in %s!\n", __func__); 95 return -ENODEV; 96 } 97 98 if (WARN_ON_ONCE(acpi_dev != dev->data)) 99 dev->data = acpi_dev; 100 101 ret = pnpacpi_build_resource_template(dev, &buffer); 102 if (ret) 103 return ret; 104 ret = pnpacpi_encode_resources(dev, &buffer); 105 if (ret) { 106 kfree(buffer.pointer); 107 return ret; 108 } 109 if (ACPI_FAILURE(acpi_set_current_resources(handle, &buffer))) 110 ret = -EINVAL; 111 else if (acpi_bus_power_manageable(handle)) 112 ret = acpi_bus_set_power(handle, ACPI_STATE_D0); 113 kfree(buffer.pointer); 114 return ret; 115 } 116 117 static int pnpacpi_disable_resources(struct pnp_dev *dev) 118 { 119 struct acpi_device *acpi_dev; 120 acpi_handle handle; 121 int ret; 122 123 dev_dbg(&dev->dev, "disable resources\n"); 124 125 handle = DEVICE_ACPI_HANDLE(&dev->dev); 126 if (!handle || ACPI_FAILURE(acpi_bus_get_device(handle, &acpi_dev))) { 127 dev_dbg(&dev->dev, "ACPI device not found in %s!\n", __func__); 128 return 0; 129 } 130 131 /* acpi_unregister_gsi(pnp_irq(dev, 0)); */ 132 ret = 0; 133 if (acpi_bus_power_manageable(handle)) 134 acpi_bus_set_power(handle, ACPI_STATE_D3); 135 /* continue even if acpi_bus_set_power() fails */ 136 if (ACPI_FAILURE(acpi_evaluate_object(handle, "_DIS", NULL, NULL))) 137 ret = -ENODEV; 138 return ret; 139 } 140 141 #ifdef CONFIG_ACPI_SLEEP 142 static bool pnpacpi_can_wakeup(struct pnp_dev *dev) 143 { 144 struct acpi_device *acpi_dev; 145 acpi_handle handle; 146 147 handle = DEVICE_ACPI_HANDLE(&dev->dev); 148 if (!handle || ACPI_FAILURE(acpi_bus_get_device(handle, &acpi_dev))) { 149 dev_dbg(&dev->dev, "ACPI device not found in %s!\n", __func__); 150 return false; 151 } 152 153 return acpi_bus_can_wakeup(handle); 154 } 155 156 static int pnpacpi_suspend(struct pnp_dev *dev, pm_message_t state) 157 { 158 struct acpi_device *acpi_dev; 159 acpi_handle handle; 160 int error = 0; 161 162 handle = DEVICE_ACPI_HANDLE(&dev->dev); 163 if (!handle || ACPI_FAILURE(acpi_bus_get_device(handle, &acpi_dev))) { 164 dev_dbg(&dev->dev, "ACPI device not found in %s!\n", __func__); 165 return 0; 166 } 167 168 if (device_can_wakeup(&dev->dev)) { 169 error = acpi_pm_device_sleep_wake(&dev->dev, 170 device_may_wakeup(&dev->dev)); 171 if (error) 172 return error; 173 } 174 175 if (acpi_bus_power_manageable(handle)) { 176 int power_state = acpi_pm_device_sleep_state(&dev->dev, NULL, 177 ACPI_STATE_D3); 178 if (power_state < 0) 179 power_state = (state.event == PM_EVENT_ON) ? 180 ACPI_STATE_D0 : ACPI_STATE_D3; 181 182 /* 183 * acpi_bus_set_power() often fails (keyboard port can't be 184 * powered-down?), and in any case, our return value is ignored 185 * by pnp_bus_suspend(). Hence we don't revert the wakeup 186 * setting if the set_power fails. 187 */ 188 error = acpi_bus_set_power(handle, power_state); 189 } 190 191 return error; 192 } 193 194 static int pnpacpi_resume(struct pnp_dev *dev) 195 { 196 struct acpi_device *acpi_dev; 197 acpi_handle handle = DEVICE_ACPI_HANDLE(&dev->dev); 198 int error = 0; 199 200 if (!handle || ACPI_FAILURE(acpi_bus_get_device(handle, &acpi_dev))) { 201 dev_dbg(&dev->dev, "ACPI device not found in %s!\n", __func__); 202 return -ENODEV; 203 } 204 205 if (device_may_wakeup(&dev->dev)) 206 acpi_pm_device_sleep_wake(&dev->dev, false); 207 208 if (acpi_bus_power_manageable(handle)) 209 error = acpi_bus_set_power(handle, ACPI_STATE_D0); 210 211 return error; 212 } 213 #endif 214 215 struct pnp_protocol pnpacpi_protocol = { 216 .name = "Plug and Play ACPI", 217 .get = pnpacpi_get_resources, 218 .set = pnpacpi_set_resources, 219 .disable = pnpacpi_disable_resources, 220 #ifdef CONFIG_ACPI_SLEEP 221 .can_wakeup = pnpacpi_can_wakeup, 222 .suspend = pnpacpi_suspend, 223 .resume = pnpacpi_resume, 224 #endif 225 }; 226 EXPORT_SYMBOL(pnpacpi_protocol); 227 228 static char *__init pnpacpi_get_id(struct acpi_device *device) 229 { 230 struct acpi_hardware_id *id; 231 232 list_for_each_entry(id, &device->pnp.ids, list) { 233 if (ispnpidacpi(id->id)) 234 return id->id; 235 } 236 237 return NULL; 238 } 239 240 static int __init pnpacpi_add_device(struct acpi_device *device) 241 { 242 acpi_handle temp = NULL; 243 acpi_status status; 244 struct pnp_dev *dev; 245 char *pnpid; 246 struct acpi_hardware_id *id; 247 248 /* Skip devices that are already bound */ 249 if (device->physical_node_count) 250 return 0; 251 252 /* 253 * If a PnPacpi device is not present , the device 254 * driver should not be loaded. 255 */ 256 status = acpi_get_handle(device->handle, "_CRS", &temp); 257 if (ACPI_FAILURE(status)) 258 return 0; 259 260 pnpid = pnpacpi_get_id(device); 261 if (!pnpid) 262 return 0; 263 264 if (is_exclusive_device(device) || !device->status.present) 265 return 0; 266 267 dev = pnp_alloc_dev(&pnpacpi_protocol, num, pnpid); 268 if (!dev) 269 return -ENOMEM; 270 271 dev->data = device; 272 /* .enabled means the device can decode the resources */ 273 dev->active = device->status.enabled; 274 status = acpi_get_handle(device->handle, "_SRS", &temp); 275 if (ACPI_SUCCESS(status)) 276 dev->capabilities |= PNP_CONFIGURABLE; 277 dev->capabilities |= PNP_READ; 278 if (device->flags.dynamic_status && (dev->capabilities & PNP_CONFIGURABLE)) 279 dev->capabilities |= PNP_WRITE; 280 if (device->flags.removable) 281 dev->capabilities |= PNP_REMOVABLE; 282 status = acpi_get_handle(device->handle, "_DIS", &temp); 283 if (ACPI_SUCCESS(status)) 284 dev->capabilities |= PNP_DISABLE; 285 286 if (strlen(acpi_device_name(device))) 287 strncpy(dev->name, acpi_device_name(device), sizeof(dev->name)); 288 else 289 strncpy(dev->name, acpi_device_bid(device), sizeof(dev->name)); 290 291 if (dev->active) 292 pnpacpi_parse_allocated_resource(dev); 293 294 if (dev->capabilities & PNP_CONFIGURABLE) 295 pnpacpi_parse_resource_option_data(dev); 296 297 list_for_each_entry(id, &device->pnp.ids, list) { 298 if (!strcmp(id->id, pnpid)) 299 continue; 300 if (!ispnpidacpi(id->id)) 301 continue; 302 pnp_add_id(dev, id->id); 303 } 304 305 /* clear out the damaged flags */ 306 if (!dev->active) 307 pnp_init_resources(dev); 308 pnp_add_device(dev); 309 num++; 310 311 return AE_OK; 312 } 313 314 static acpi_status __init pnpacpi_add_device_handler(acpi_handle handle, 315 u32 lvl, void *context, 316 void **rv) 317 { 318 struct acpi_device *device; 319 320 if (!acpi_bus_get_device(handle, &device)) 321 pnpacpi_add_device(device); 322 else 323 return AE_CTRL_DEPTH; 324 return AE_OK; 325 } 326 327 static int __init acpi_pnp_match(struct device *dev, void *_pnp) 328 { 329 struct acpi_device *acpi = to_acpi_device(dev); 330 struct pnp_dev *pnp = _pnp; 331 332 /* true means it matched */ 333 return !acpi->physical_node_count 334 && compare_pnp_id(pnp->id, acpi_device_hid(acpi)); 335 } 336 337 static int __init acpi_pnp_find_device(struct device *dev, acpi_handle * handle) 338 { 339 struct device *adev; 340 struct acpi_device *acpi; 341 342 adev = bus_find_device(&acpi_bus_type, NULL, 343 to_pnp_dev(dev), acpi_pnp_match); 344 if (!adev) 345 return -ENODEV; 346 347 acpi = to_acpi_device(adev); 348 *handle = acpi->handle; 349 put_device(adev); 350 return 0; 351 } 352 353 /* complete initialization of a PNPACPI device includes having 354 * pnpdev->dev.archdata.acpi_handle point to its ACPI sibling. 355 */ 356 static struct acpi_bus_type __initdata acpi_pnp_bus = { 357 .bus = &pnp_bus_type, 358 .find_device = acpi_pnp_find_device, 359 }; 360 361 int pnpacpi_disabled __initdata; 362 static int __init pnpacpi_init(void) 363 { 364 if (acpi_disabled || pnpacpi_disabled) { 365 printk(KERN_INFO "pnp: PnP ACPI: disabled\n"); 366 return 0; 367 } 368 printk(KERN_INFO "pnp: PnP ACPI init\n"); 369 pnp_register_protocol(&pnpacpi_protocol); 370 register_acpi_bus_type(&acpi_pnp_bus); 371 acpi_get_devices(NULL, pnpacpi_add_device_handler, NULL, NULL); 372 printk(KERN_INFO "pnp: PnP ACPI: found %d devices\n", num); 373 unregister_acpi_bus_type(&acpi_pnp_bus); 374 pnp_platform_devices = 1; 375 return 0; 376 } 377 378 fs_initcall(pnpacpi_init); 379 380 static int __init pnpacpi_setup(char *str) 381 { 382 if (str == NULL) 383 return 1; 384 if (!strncmp(str, "off", 3)) 385 pnpacpi_disabled = 1; 386 return 1; 387 } 388 389 __setup("pnpacpi=", pnpacpi_setup); 390