uboot/arch/x86/cpu/apollolake/punit.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * Copyright 2019 Google LLC
   4 */
   5
   6#include <common.h>
   7#include <dm.h>
   8#include <log.h>
   9#include <spl.h>
  10#include <asm/cpu.h>
  11#include <asm/cpu_common.h>
  12#include <asm/intel_regs.h>
  13#include <asm/io.h>
  14#include <asm/pci.h>
  15#include <asm/arch/systemagent.h>
  16#include <linux/delay.h>
  17
  18/*
  19 * Punit Initialisation code. This all isn't documented, but
  20 * this is the recipe.
  21 */
  22static int punit_init(struct udevice *dev)
  23{
  24        struct udevice *cpu;
  25        u32 reg;
  26        ulong start;
  27        int ret;
  28
  29        /* Thermal throttle activation offset */
  30        ret = uclass_first_device_err(UCLASS_CPU, &cpu);
  31        if (ret)
  32                return log_msg_ret("Cannot find CPU", ret);
  33        cpu_configure_thermal_target(cpu);
  34
  35        /*
  36         * Software Core Disable Mask (P_CR_CORE_DISABLE_MASK_0_0_0_MCHBAR).
  37         * Enable all cores here.
  38         */
  39        writel(0, MCHBAR_REG(CORE_DISABLE_MASK));
  40
  41        /* P-Unit bring up */
  42        reg = readl(MCHBAR_REG(BIOS_RESET_CPL));
  43        if (reg == 0xffffffff) {
  44                /* P-unit not found */
  45                debug("Punit MMIO not available\n");
  46                return -ENOENT;
  47        }
  48
  49        /* Set Punit interrupt pin IPIN offset 3D */
  50        dm_pci_write_config8(dev, PCI_INTERRUPT_PIN, 0x2);
  51
  52        /* Set PUINT IRQ to 24 and INTPIN LOCK */
  53        writel(PUINT_THERMAL_DEVICE_IRQ_VEC_NUMBER |
  54               PUINT_THERMAL_DEVICE_IRQ_LOCK,
  55               MCHBAR_REG(PUNIT_THERMAL_DEVICE_IRQ));
  56
  57        /* Stage0 BIOS Reset Complete (RST_CPL) */
  58        enable_bios_reset_cpl();
  59
  60        /*
  61         * Poll for bit 8 to check if PCODE has completed its action in response
  62         * to BIOS Reset complete.  We wait here till 1 ms for the bit to get
  63         * set.
  64         */
  65        start = get_timer(0);
  66        while (!(readl(MCHBAR_REG(BIOS_RESET_CPL)) & PCODE_INIT_DONE)) {
  67                if (get_timer(start) > 1) {
  68                        debug("PCODE Init Done timeout\n");
  69                        return -ETIMEDOUT;
  70                }
  71                udelay(100);
  72        }
  73        debug("PUNIT init complete\n");
  74
  75        return 0;
  76}
  77
  78static int apl_punit_probe(struct udevice *dev)
  79{
  80        if (spl_phase() == PHASE_SPL)
  81                return punit_init(dev);
  82
  83        return 0;
  84}
  85
  86static const struct udevice_id apl_syscon_ids[] = {
  87        { .compatible = "intel,apl-punit", .data = X86_SYSCON_PUNIT },
  88        { }
  89};
  90
  91U_BOOT_DRIVER(intel_apl_punit) = {
  92        .name           = "intel_apl_punit",
  93        .id             = UCLASS_SYSCON,
  94        .of_match       = apl_syscon_ids,
  95        .probe          = apl_punit_probe,
  96        DM_HEADER(<asm/cpu.h>)    /* for X86_SYSCON_PUNIT */
  97};
  98