pci-acpi.c 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260
  1. /*
  2. * File: pci-acpi.c
  3. * Purpose: Provide PCI support in ACPI
  4. *
  5. * Copyright (C) 2005 David Shaohua Li <shaohua.li@intel.com>
  6. * Copyright (C) 2004 Tom Long Nguyen <tom.l.nguyen@intel.com>
  7. * Copyright (C) 2004 Intel Corp.
  8. */
  9. #include <linux/delay.h>
  10. #include <linux/init.h>
  11. #include <linux/pci.h>
  12. #include <linux/module.h>
  13. #include <acpi/acpi.h>
  14. #include <acpi/acnamesp.h>
  15. #include <acpi/acresrc.h>
  16. #include <acpi/acpi_bus.h>
  17. #include <linux/pci-acpi.h>
  18. static u32 ctrlset_buf[3] = {0, 0, 0};
  19. static u32 global_ctrlsets = 0;
  20. static u8 OSC_UUID[16] = {0x5B, 0x4D, 0xDB, 0x33, 0xF7, 0x1F, 0x1C, 0x40, 0x96, 0x57, 0x74, 0x41, 0xC0, 0x3D, 0xD7, 0x66};
  21. static acpi_status
  22. acpi_query_osc (
  23. acpi_handle handle,
  24. u32 level,
  25. void *context,
  26. void **retval )
  27. {
  28. acpi_status status;
  29. struct acpi_object_list input;
  30. union acpi_object in_params[4];
  31. struct acpi_buffer output;
  32. union acpi_object out_obj;
  33. u32 osc_dw0;
  34. /* Setting up output buffer */
  35. output.length = sizeof(out_obj) + 3*sizeof(u32);
  36. output.pointer = &out_obj;
  37. /* Setting up input parameters */
  38. input.count = 4;
  39. input.pointer = in_params;
  40. in_params[0].type = ACPI_TYPE_BUFFER;
  41. in_params[0].buffer.length = 16;
  42. in_params[0].buffer.pointer = OSC_UUID;
  43. in_params[1].type = ACPI_TYPE_INTEGER;
  44. in_params[1].integer.value = 1;
  45. in_params[2].type = ACPI_TYPE_INTEGER;
  46. in_params[2].integer.value = 3;
  47. in_params[3].type = ACPI_TYPE_BUFFER;
  48. in_params[3].buffer.length = 12;
  49. in_params[3].buffer.pointer = (u8 *)context;
  50. status = acpi_evaluate_object(handle, "_OSC", &input, &output);
  51. if (ACPI_FAILURE (status)) {
  52. printk(KERN_DEBUG
  53. "Evaluate _OSC Set fails. Status = 0x%04x\n", status);
  54. return status;
  55. }
  56. if (out_obj.type != ACPI_TYPE_BUFFER) {
  57. printk(KERN_DEBUG
  58. "Evaluate _OSC returns wrong type\n");
  59. return AE_TYPE;
  60. }
  61. osc_dw0 = *((u32 *) out_obj.buffer.pointer);
  62. if (osc_dw0) {
  63. if (osc_dw0 & OSC_REQUEST_ERROR)
  64. printk(KERN_DEBUG "_OSC request fails\n");
  65. if (osc_dw0 & OSC_INVALID_UUID_ERROR)
  66. printk(KERN_DEBUG "_OSC invalid UUID\n");
  67. if (osc_dw0 & OSC_INVALID_REVISION_ERROR)
  68. printk(KERN_DEBUG "_OSC invalid revision\n");
  69. if (osc_dw0 & OSC_CAPABILITIES_MASK_ERROR) {
  70. /* Update Global Control Set */
  71. global_ctrlsets = *((u32 *)(out_obj.buffer.pointer+8));
  72. return AE_OK;
  73. }
  74. return AE_ERROR;
  75. }
  76. /* Update Global Control Set */
  77. global_ctrlsets = *((u32 *)(out_obj.buffer.pointer + 8));
  78. return AE_OK;
  79. }
  80. static acpi_status
  81. acpi_run_osc (
  82. acpi_handle handle,
  83. u32 level,
  84. void *context,
  85. void **retval )
  86. {
  87. acpi_status status;
  88. struct acpi_object_list input;
  89. union acpi_object in_params[4];
  90. struct acpi_buffer output;
  91. union acpi_object out_obj;
  92. u32 osc_dw0;
  93. /* Setting up output buffer */
  94. output.length = sizeof(out_obj) + 3*sizeof(u32);
  95. output.pointer = &out_obj;
  96. /* Setting up input parameters */
  97. input.count = 4;
  98. input.pointer = in_params;
  99. in_params[0].type = ACPI_TYPE_BUFFER;
  100. in_params[0].buffer.length = 16;
  101. in_params[0].buffer.pointer = OSC_UUID;
  102. in_params[1].type = ACPI_TYPE_INTEGER;
  103. in_params[1].integer.value = 1;
  104. in_params[2].type = ACPI_TYPE_INTEGER;
  105. in_params[2].integer.value = 3;
  106. in_params[3].type = ACPI_TYPE_BUFFER;
  107. in_params[3].buffer.length = 12;
  108. in_params[3].buffer.pointer = (u8 *)context;
  109. status = acpi_evaluate_object(handle, "_OSC", &input, &output);
  110. if (ACPI_FAILURE (status)) {
  111. printk(KERN_DEBUG
  112. "Evaluate _OSC Set fails. Status = 0x%04x\n", status);
  113. return status;
  114. }
  115. if (out_obj.type != ACPI_TYPE_BUFFER) {
  116. printk(KERN_DEBUG
  117. "Evaluate _OSC returns wrong type\n");
  118. return AE_TYPE;
  119. }
  120. osc_dw0 = *((u32 *) out_obj.buffer.pointer);
  121. if (osc_dw0) {
  122. if (osc_dw0 & OSC_REQUEST_ERROR)
  123. printk(KERN_DEBUG "_OSC request fails\n");
  124. if (osc_dw0 & OSC_INVALID_UUID_ERROR)
  125. printk(KERN_DEBUG "_OSC invalid UUID\n");
  126. if (osc_dw0 & OSC_INVALID_REVISION_ERROR)
  127. printk(KERN_DEBUG "_OSC invalid revision\n");
  128. if (osc_dw0 & OSC_CAPABILITIES_MASK_ERROR) {
  129. printk(KERN_DEBUG "_OSC FW not grant req. control\n");
  130. return AE_SUPPORT;
  131. }
  132. return AE_ERROR;
  133. }
  134. return AE_OK;
  135. }
  136. /**
  137. * pci_osc_support_set - register OS support to Firmware
  138. * @flags: OS support bits
  139. *
  140. * Update OS support fields and doing a _OSC Query to obtain an update
  141. * from Firmware on supported control bits.
  142. **/
  143. acpi_status pci_osc_support_set(u32 flags)
  144. {
  145. u32 temp;
  146. if (!(flags & OSC_SUPPORT_MASKS)) {
  147. return AE_TYPE;
  148. }
  149. ctrlset_buf[OSC_SUPPORT_TYPE] |= (flags & OSC_SUPPORT_MASKS);
  150. /* do _OSC query for all possible controls */
  151. temp = ctrlset_buf[OSC_CONTROL_TYPE];
  152. ctrlset_buf[OSC_QUERY_TYPE] = OSC_QUERY_ENABLE;
  153. ctrlset_buf[OSC_CONTROL_TYPE] = OSC_CONTROL_MASKS;
  154. acpi_get_devices ( PCI_ROOT_HID_STRING,
  155. acpi_query_osc,
  156. ctrlset_buf,
  157. NULL );
  158. ctrlset_buf[OSC_QUERY_TYPE] = !OSC_QUERY_ENABLE;
  159. ctrlset_buf[OSC_CONTROL_TYPE] = temp;
  160. return AE_OK;
  161. }
  162. EXPORT_SYMBOL(pci_osc_support_set);
  163. /**
  164. * pci_osc_control_set - commit requested control to Firmware
  165. * @flags: driver's requested control bits
  166. *
  167. * Attempt to take control from Firmware on requested control bits.
  168. **/
  169. acpi_status pci_osc_control_set(u32 flags)
  170. {
  171. acpi_status status;
  172. u32 ctrlset;
  173. ctrlset = (flags & OSC_CONTROL_MASKS);
  174. if (!ctrlset) {
  175. return AE_TYPE;
  176. }
  177. if (ctrlset_buf[OSC_SUPPORT_TYPE] &&
  178. ((global_ctrlsets & ctrlset) != ctrlset)) {
  179. return AE_SUPPORT;
  180. }
  181. ctrlset_buf[OSC_CONTROL_TYPE] |= ctrlset;
  182. status = acpi_get_devices ( PCI_ROOT_HID_STRING,
  183. acpi_run_osc,
  184. ctrlset_buf,
  185. NULL );
  186. if (ACPI_FAILURE (status)) {
  187. ctrlset_buf[OSC_CONTROL_TYPE] &= ~ctrlset;
  188. }
  189. return status;
  190. }
  191. EXPORT_SYMBOL(pci_osc_control_set);
  192. /* ACPI bus type */
  193. static int pci_acpi_find_device(struct device *dev, acpi_handle *handle)
  194. {
  195. struct pci_dev * pci_dev;
  196. acpi_integer addr;
  197. pci_dev = to_pci_dev(dev);
  198. /* Please ref to ACPI spec for the syntax of _ADR */
  199. addr = (PCI_SLOT(pci_dev->devfn) << 16) | PCI_FUNC(pci_dev->devfn);
  200. *handle = acpi_get_child(DEVICE_ACPI_HANDLE(dev->parent), addr);
  201. if (!*handle)
  202. return -ENODEV;
  203. return 0;
  204. }
  205. static int pci_acpi_find_root_bridge(struct device *dev, acpi_handle *handle)
  206. {
  207. int num;
  208. unsigned int seg, bus;
  209. /*
  210. * The string should be the same as root bridge's name
  211. * Please look at 'pci_scan_bus_parented'
  212. */
  213. num = sscanf(dev->bus_id, "pci%04x:%02x", &seg, &bus);
  214. if (num != 2)
  215. return -ENODEV;
  216. *handle = acpi_get_pci_rootbridge_handle(seg, bus);
  217. if (!*handle)
  218. return -ENODEV;
  219. return 0;
  220. }
  221. static struct acpi_bus_type pci_acpi_bus = {
  222. .bus = &pci_bus_type,
  223. .find_device = pci_acpi_find_device,
  224. .find_bridge = pci_acpi_find_root_bridge,
  225. };
  226. static int __init pci_acpi_init(void)
  227. {
  228. int ret;
  229. ret = register_acpi_bus_type(&pci_acpi_bus);
  230. if (ret)
  231. return 0;
  232. return 0;
  233. }
  234. arch_initcall(pci_acpi_init);