acpi_table.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * Based on acpi.c from coreboot
  4. *
  5. * Copyright (C) 2015, Saket Sinha <saket.sinha89@gmail.com>
  6. * Copyright (C) 2016, Bin Meng <bmeng.cn@gmail.com>
  7. */
  8. #include <common.h>
  9. #include <cpu.h>
  10. #include <dm.h>
  11. #include <log.h>
  12. #include <dm/uclass-internal.h>
  13. #include <mapmem.h>
  14. #include <serial.h>
  15. #include <version.h>
  16. #include <acpi/acpigen.h>
  17. #include <acpi/acpi_table.h>
  18. #include <asm/acpi/global_nvs.h>
  19. #include <asm/ioapic.h>
  20. #include <asm/lapic.h>
  21. #include <asm/mpspec.h>
  22. #include <asm/tables.h>
  23. #include <asm/arch/global_nvs.h>
  24. #include <dm/acpi.h>
  25. #include <linux/err.h>
  26. /*
  27. * IASL compiles the dsdt entries and writes the hex values
  28. * to a C array AmlCode[] (see dsdt.c).
  29. */
  30. extern const unsigned char AmlCode[];
  31. /* ACPI RSDP address to be used in boot parameters */
  32. static ulong acpi_rsdp_addr;
  33. static void acpi_create_facs(struct acpi_facs *facs)
  34. {
  35. memset((void *)facs, 0, sizeof(struct acpi_facs));
  36. memcpy(facs->signature, "FACS", 4);
  37. facs->length = sizeof(struct acpi_facs);
  38. facs->hardware_signature = 0;
  39. facs->firmware_waking_vector = 0;
  40. facs->global_lock = 0;
  41. facs->flags = 0;
  42. facs->x_firmware_waking_vector_l = 0;
  43. facs->x_firmware_waking_vector_h = 0;
  44. facs->version = 1;
  45. }
  46. static int acpi_create_madt_lapic(struct acpi_madt_lapic *lapic,
  47. u8 cpu, u8 apic)
  48. {
  49. lapic->type = ACPI_APIC_LAPIC;
  50. lapic->length = sizeof(struct acpi_madt_lapic);
  51. lapic->flags = LOCAL_APIC_FLAG_ENABLED;
  52. lapic->processor_id = cpu;
  53. lapic->apic_id = apic;
  54. return lapic->length;
  55. }
  56. int acpi_create_madt_lapics(u32 current)
  57. {
  58. struct udevice *dev;
  59. int total_length = 0;
  60. for (uclass_find_first_device(UCLASS_CPU, &dev);
  61. dev;
  62. uclass_find_next_device(&dev)) {
  63. struct cpu_platdata *plat = dev_get_parent_platdata(dev);
  64. int length = acpi_create_madt_lapic(
  65. (struct acpi_madt_lapic *)current,
  66. plat->cpu_id, plat->cpu_id);
  67. current += length;
  68. total_length += length;
  69. }
  70. return total_length;
  71. }
  72. int acpi_create_madt_ioapic(struct acpi_madt_ioapic *ioapic, u8 id,
  73. u32 addr, u32 gsi_base)
  74. {
  75. ioapic->type = ACPI_APIC_IOAPIC;
  76. ioapic->length = sizeof(struct acpi_madt_ioapic);
  77. ioapic->reserved = 0x00;
  78. ioapic->gsi_base = gsi_base;
  79. ioapic->ioapic_id = id;
  80. ioapic->ioapic_addr = addr;
  81. return ioapic->length;
  82. }
  83. int acpi_create_madt_irqoverride(struct acpi_madt_irqoverride *irqoverride,
  84. u8 bus, u8 source, u32 gsirq, u16 flags)
  85. {
  86. irqoverride->type = ACPI_APIC_IRQ_SRC_OVERRIDE;
  87. irqoverride->length = sizeof(struct acpi_madt_irqoverride);
  88. irqoverride->bus = bus;
  89. irqoverride->source = source;
  90. irqoverride->gsirq = gsirq;
  91. irqoverride->flags = flags;
  92. return irqoverride->length;
  93. }
  94. int acpi_create_madt_lapic_nmi(struct acpi_madt_lapic_nmi *lapic_nmi,
  95. u8 cpu, u16 flags, u8 lint)
  96. {
  97. lapic_nmi->type = ACPI_APIC_LAPIC_NMI;
  98. lapic_nmi->length = sizeof(struct acpi_madt_lapic_nmi);
  99. lapic_nmi->flags = flags;
  100. lapic_nmi->processor_id = cpu;
  101. lapic_nmi->lint = lint;
  102. return lapic_nmi->length;
  103. }
  104. static int acpi_create_madt_irq_overrides(u32 current)
  105. {
  106. struct acpi_madt_irqoverride *irqovr;
  107. u16 sci_flags = MP_IRQ_TRIGGER_LEVEL | MP_IRQ_POLARITY_HIGH;
  108. int length = 0;
  109. irqovr = (void *)current;
  110. length += acpi_create_madt_irqoverride(irqovr, 0, 0, 2, 0);
  111. irqovr = (void *)(current + length);
  112. length += acpi_create_madt_irqoverride(irqovr, 0, 9, 9, sci_flags);
  113. return length;
  114. }
  115. __weak u32 acpi_fill_madt(u32 current)
  116. {
  117. current += acpi_create_madt_lapics(current);
  118. current += acpi_create_madt_ioapic((struct acpi_madt_ioapic *)current,
  119. io_apic_read(IO_APIC_ID) >> 24, IO_APIC_ADDR, 0);
  120. current += acpi_create_madt_irq_overrides(current);
  121. return current;
  122. }
  123. static void acpi_create_madt(struct acpi_madt *madt)
  124. {
  125. struct acpi_table_header *header = &(madt->header);
  126. u32 current = (u32)madt + sizeof(struct acpi_madt);
  127. memset((void *)madt, 0, sizeof(struct acpi_madt));
  128. /* Fill out header fields */
  129. acpi_fill_header(header, "APIC");
  130. header->length = sizeof(struct acpi_madt);
  131. header->revision = ACPI_MADT_REV_ACPI_3_0;
  132. madt->lapic_addr = LAPIC_DEFAULT_BASE;
  133. madt->flags = ACPI_MADT_PCAT_COMPAT;
  134. current = acpi_fill_madt(current);
  135. /* (Re)calculate length and checksum */
  136. header->length = current - (u32)madt;
  137. header->checksum = table_compute_checksum((void *)madt, header->length);
  138. }
  139. int acpi_create_mcfg_mmconfig(struct acpi_mcfg_mmconfig *mmconfig, u32 base,
  140. u16 seg_nr, u8 start, u8 end)
  141. {
  142. memset(mmconfig, 0, sizeof(*mmconfig));
  143. mmconfig->base_address_l = base;
  144. mmconfig->base_address_h = 0;
  145. mmconfig->pci_segment_group_number = seg_nr;
  146. mmconfig->start_bus_number = start;
  147. mmconfig->end_bus_number = end;
  148. return sizeof(struct acpi_mcfg_mmconfig);
  149. }
  150. __weak u32 acpi_fill_mcfg(u32 current)
  151. {
  152. current += acpi_create_mcfg_mmconfig
  153. ((struct acpi_mcfg_mmconfig *)current,
  154. CONFIG_PCIE_ECAM_BASE, 0x0, 0x0, 255);
  155. return current;
  156. }
  157. /* MCFG is defined in the PCI Firmware Specification 3.0 */
  158. static void acpi_create_mcfg(struct acpi_mcfg *mcfg)
  159. {
  160. struct acpi_table_header *header = &(mcfg->header);
  161. u32 current = (u32)mcfg + sizeof(struct acpi_mcfg);
  162. memset((void *)mcfg, 0, sizeof(struct acpi_mcfg));
  163. /* Fill out header fields */
  164. acpi_fill_header(header, "MCFG");
  165. header->length = sizeof(struct acpi_mcfg);
  166. header->revision = 1;
  167. current = acpi_fill_mcfg(current);
  168. /* (Re)calculate length and checksum */
  169. header->length = current - (u32)mcfg;
  170. header->checksum = table_compute_checksum((void *)mcfg, header->length);
  171. }
  172. __weak u32 acpi_fill_csrt(u32 current)
  173. {
  174. return 0;
  175. }
  176. static int acpi_create_csrt(struct acpi_csrt *csrt)
  177. {
  178. struct acpi_table_header *header = &(csrt->header);
  179. u32 current = (u32)csrt + sizeof(struct acpi_csrt);
  180. uint ptr;
  181. memset((void *)csrt, 0, sizeof(struct acpi_csrt));
  182. /* Fill out header fields */
  183. acpi_fill_header(header, "CSRT");
  184. header->length = sizeof(struct acpi_csrt);
  185. header->revision = 0;
  186. ptr = acpi_fill_csrt(current);
  187. if (!ptr)
  188. return -ENOENT;
  189. current = ptr;
  190. /* (Re)calculate length and checksum */
  191. header->length = current - (u32)csrt;
  192. header->checksum = table_compute_checksum((void *)csrt, header->length);
  193. return 0;
  194. }
  195. static void acpi_create_spcr(struct acpi_spcr *spcr)
  196. {
  197. struct acpi_table_header *header = &(spcr->header);
  198. struct serial_device_info serial_info = {0};
  199. ulong serial_address, serial_offset;
  200. struct udevice *dev;
  201. uint serial_config;
  202. uint serial_width;
  203. int access_size;
  204. int space_id;
  205. int ret = -ENODEV;
  206. /* Fill out header fields */
  207. acpi_fill_header(header, "SPCR");
  208. header->length = sizeof(struct acpi_spcr);
  209. header->revision = 2;
  210. /* Read the device once, here. It is reused below */
  211. dev = gd->cur_serial_dev;
  212. if (dev)
  213. ret = serial_getinfo(dev, &serial_info);
  214. if (ret)
  215. serial_info.type = SERIAL_CHIP_UNKNOWN;
  216. /* Encode chip type */
  217. switch (serial_info.type) {
  218. case SERIAL_CHIP_16550_COMPATIBLE:
  219. spcr->interface_type = ACPI_DBG2_16550_COMPATIBLE;
  220. break;
  221. case SERIAL_CHIP_UNKNOWN:
  222. default:
  223. spcr->interface_type = ACPI_DBG2_UNKNOWN;
  224. break;
  225. }
  226. /* Encode address space */
  227. switch (serial_info.addr_space) {
  228. case SERIAL_ADDRESS_SPACE_MEMORY:
  229. space_id = ACPI_ADDRESS_SPACE_MEMORY;
  230. break;
  231. case SERIAL_ADDRESS_SPACE_IO:
  232. default:
  233. space_id = ACPI_ADDRESS_SPACE_IO;
  234. break;
  235. }
  236. serial_width = serial_info.reg_width * 8;
  237. serial_offset = serial_info.reg_offset << serial_info.reg_shift;
  238. serial_address = serial_info.addr + serial_offset;
  239. /* Encode register access size */
  240. switch (serial_info.reg_shift) {
  241. case 0:
  242. access_size = ACPI_ACCESS_SIZE_BYTE_ACCESS;
  243. break;
  244. case 1:
  245. access_size = ACPI_ACCESS_SIZE_WORD_ACCESS;
  246. break;
  247. case 2:
  248. access_size = ACPI_ACCESS_SIZE_DWORD_ACCESS;
  249. break;
  250. case 3:
  251. access_size = ACPI_ACCESS_SIZE_QWORD_ACCESS;
  252. break;
  253. default:
  254. access_size = ACPI_ACCESS_SIZE_UNDEFINED;
  255. break;
  256. }
  257. debug("UART type %u @ %lx\n", spcr->interface_type, serial_address);
  258. /* Fill GAS */
  259. spcr->serial_port.space_id = space_id;
  260. spcr->serial_port.bit_width = serial_width;
  261. spcr->serial_port.bit_offset = 0;
  262. spcr->serial_port.access_size = access_size;
  263. spcr->serial_port.addrl = lower_32_bits(serial_address);
  264. spcr->serial_port.addrh = upper_32_bits(serial_address);
  265. /* Encode baud rate */
  266. switch (serial_info.baudrate) {
  267. case 9600:
  268. spcr->baud_rate = 3;
  269. break;
  270. case 19200:
  271. spcr->baud_rate = 4;
  272. break;
  273. case 57600:
  274. spcr->baud_rate = 6;
  275. break;
  276. case 115200:
  277. spcr->baud_rate = 7;
  278. break;
  279. default:
  280. spcr->baud_rate = 0;
  281. break;
  282. }
  283. serial_config = SERIAL_DEFAULT_CONFIG;
  284. if (dev)
  285. ret = serial_getconfig(dev, &serial_config);
  286. spcr->parity = SERIAL_GET_PARITY(serial_config);
  287. spcr->stop_bits = SERIAL_GET_STOP(serial_config);
  288. /* No PCI devices for now */
  289. spcr->pci_device_id = 0xffff;
  290. spcr->pci_vendor_id = 0xffff;
  291. /*
  292. * SPCR has no clue if the UART base clock speed is different
  293. * to the default one. However, the SPCR 1.04 defines baud rate
  294. * 0 as a preconfigured state of UART and OS is supposed not
  295. * to touch the configuration of the serial device.
  296. */
  297. if (serial_info.clock != SERIAL_DEFAULT_CLOCK)
  298. spcr->baud_rate = 0;
  299. /* Fix checksum */
  300. header->checksum = table_compute_checksum((void *)spcr, header->length);
  301. }
  302. void acpi_create_ssdt(struct acpi_ctx *ctx, struct acpi_table_header *ssdt,
  303. const char *oem_table_id)
  304. {
  305. memset((void *)ssdt, '\0', sizeof(struct acpi_table_header));
  306. acpi_fill_header(ssdt, "SSDT");
  307. ssdt->revision = acpi_get_table_revision(ACPITAB_SSDT);
  308. ssdt->aslc_revision = 1;
  309. ssdt->length = sizeof(struct acpi_table_header);
  310. acpi_inc(ctx, sizeof(struct acpi_table_header));
  311. acpi_fill_ssdt(ctx);
  312. /* (Re)calculate length and checksum. */
  313. ssdt->length = ctx->current - (void *)ssdt;
  314. ssdt->checksum = table_compute_checksum((void *)ssdt, ssdt->length);
  315. }
  316. /*
  317. * QEMU's version of write_acpi_tables is defined in drivers/misc/qfw.c
  318. */
  319. ulong write_acpi_tables(ulong start_addr)
  320. {
  321. struct acpi_ctx sctx, *ctx = &sctx;
  322. struct acpi_facs *facs;
  323. struct acpi_table_header *dsdt;
  324. struct acpi_fadt *fadt;
  325. struct acpi_table_header *ssdt;
  326. struct acpi_mcfg *mcfg;
  327. struct acpi_madt *madt;
  328. struct acpi_csrt *csrt;
  329. struct acpi_spcr *spcr;
  330. void *start;
  331. ulong addr;
  332. int i;
  333. start = map_sysmem(start_addr, 0);
  334. debug("ACPI: Writing ACPI tables at %lx\n", start_addr);
  335. acpi_setup_base_tables(ctx, start);
  336. debug("ACPI: * FACS\n");
  337. facs = ctx->current;
  338. acpi_inc_align(ctx, sizeof(struct acpi_facs));
  339. acpi_create_facs(facs);
  340. debug("ACPI: * DSDT\n");
  341. dsdt = ctx->current;
  342. /* Put the table header first */
  343. memcpy(dsdt, &AmlCode, sizeof(struct acpi_table_header));
  344. acpi_inc(ctx, sizeof(struct acpi_table_header));
  345. /* If the table is not empty, allow devices to inject things */
  346. if (dsdt->length >= sizeof(struct acpi_table_header))
  347. acpi_inject_dsdt(ctx);
  348. /* Copy in the AML code itself if any (after the header) */
  349. memcpy(ctx->current,
  350. (char *)&AmlCode + sizeof(struct acpi_table_header),
  351. dsdt->length - sizeof(struct acpi_table_header));
  352. acpi_inc_align(ctx, dsdt->length - sizeof(struct acpi_table_header));
  353. /* Pack GNVS into the ACPI table area */
  354. for (i = 0; i < dsdt->length; i++) {
  355. u32 *gnvs = (u32 *)((u32)dsdt + i);
  356. if (*gnvs == ACPI_GNVS_ADDR) {
  357. ulong addr = (ulong)map_to_sysmem(ctx->current);
  358. debug("Fix up global NVS in DSDT to %#08lx\n", addr);
  359. *gnvs = addr;
  360. break;
  361. }
  362. }
  363. /*
  364. * Recalculate the length and update the DSDT checksum since we patched
  365. * the GNVS address. Set the checksum to zero since it is part of the
  366. * region being checksummed.
  367. */
  368. dsdt->length = ctx->current - (void *)dsdt;
  369. dsdt->checksum = 0;
  370. dsdt->checksum = table_compute_checksum((void *)dsdt, dsdt->length);
  371. /*
  372. * Fill in platform-specific global NVS variables. If this fails we
  373. * cannot return the error but this should only happen while debugging.
  374. */
  375. addr = acpi_create_gnvs(ctx->current);
  376. if (IS_ERR_VALUE(addr))
  377. printf("Error: Failed to create GNVS\n");
  378. acpi_inc_align(ctx, sizeof(struct acpi_global_nvs));
  379. debug("ACPI: * FADT\n");
  380. fadt = ctx->current;
  381. acpi_inc_align(ctx, sizeof(struct acpi_fadt));
  382. acpi_create_fadt(fadt, facs, dsdt);
  383. acpi_add_table(ctx, fadt);
  384. debug("ACPI: * SSDT\n");
  385. ssdt = (struct acpi_table_header *)ctx->current;
  386. acpi_create_ssdt(ctx, ssdt, OEM_TABLE_ID);
  387. if (ssdt->length > sizeof(struct acpi_table_header)) {
  388. acpi_inc_align(ctx, ssdt->length);
  389. acpi_add_table(ctx, ssdt);
  390. }
  391. debug("ACPI: * MCFG\n");
  392. mcfg = ctx->current;
  393. acpi_create_mcfg(mcfg);
  394. acpi_inc_align(ctx, mcfg->header.length);
  395. acpi_add_table(ctx, mcfg);
  396. debug("ACPI: * MADT\n");
  397. madt = ctx->current;
  398. acpi_create_madt(madt);
  399. acpi_inc_align(ctx, madt->header.length);
  400. acpi_add_table(ctx, madt);
  401. debug("ACPI: * CSRT\n");
  402. csrt = ctx->current;
  403. if (!acpi_create_csrt(csrt)) {
  404. acpi_inc_align(ctx, csrt->header.length);
  405. acpi_add_table(ctx, csrt);
  406. }
  407. debug("ACPI: * SPCR\n");
  408. spcr = ctx->current;
  409. acpi_create_spcr(spcr);
  410. acpi_inc_align(ctx, spcr->header.length);
  411. acpi_add_table(ctx, spcr);
  412. acpi_write_dev_tables(ctx);
  413. addr = map_to_sysmem(ctx->current);
  414. debug("current = %lx\n", addr);
  415. acpi_rsdp_addr = (unsigned long)ctx->rsdp;
  416. debug("ACPI: done\n");
  417. return addr;
  418. }
  419. ulong acpi_get_rsdp_addr(void)
  420. {
  421. return acpi_rsdp_addr;
  422. }