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