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