[U-Boot] [PATCH v2 18/20] x86: Add a CPU driver for baytrail

Simon Glass sjg at chromium.org
Wed Apr 29 16:34:28 CEST 2015


Hi Bin,

On 29 April 2015 at 08:25, Bin Meng <bmeng.cn at gmail.com> wrote:
> Hi Simon,
>
> On Wed, Apr 29, 2015 at 10:00 PM, Simon Glass <sjg at chromium.org> wrote:
>> Hi Bin,
>>
>> On 29 April 2015 at 07:57, Bin Meng <bmeng.cn at gmail.com> wrote:
>>> Hi Simon,
>>>
>>> On Wed, Apr 29, 2015 at 10:25 AM, Simon Glass <sjg at chromium.org> wrote:
>>>> This driver supports multi-core init and sets up the CPU frequencies
>>>> correctly.
>>>>
>>>> Signed-off-by: Simon Glass <sjg at chromium.org>
>>>> ---
>>>>
>>>> Changes in v2: None
>>>>
>>>>  arch/x86/cpu/baytrail/Makefile           |   1 +
>>>>  arch/x86/cpu/baytrail/cpu.c              | 206 +++++++++++++++++++++++++++++++
>>>>  arch/x86/include/asm/arch-baytrail/msr.h |  30 +++++
>>>>  3 files changed, 237 insertions(+)
>>>>  create mode 100644 arch/x86/cpu/baytrail/cpu.c
>>>>  create mode 100644 arch/x86/include/asm/arch-baytrail/msr.h
>>>>
>>>> diff --git a/arch/x86/cpu/baytrail/Makefile b/arch/x86/cpu/baytrail/Makefile
>>>> index 8914e8b..c78b644 100644
>>>> --- a/arch/x86/cpu/baytrail/Makefile
>>>> +++ b/arch/x86/cpu/baytrail/Makefile
>>>> @@ -4,6 +4,7 @@
>>>>  # SPDX-License-Identifier:     GPL-2.0+
>>>>  #
>>>>
>>>> +obj-y += cpu.o
>>>>  obj-y += early_uart.o
>>>>  obj-y += fsp_configs.o
>>>>  obj-y += pci.o
>>>> diff --git a/arch/x86/cpu/baytrail/cpu.c b/arch/x86/cpu/baytrail/cpu.c
>>>> new file mode 100644
>>>> index 0000000..5a2a8ee
>>>> --- /dev/null
>>>> +++ b/arch/x86/cpu/baytrail/cpu.c
>>>> @@ -0,0 +1,206 @@
>>>> +/*
>>>> + * Copyright (C) 2015 Google, Inc
>>>> + *
>>>> + * SPDX-License-Identifier:    GPL-2.0+
>>>> + *
>>>> + * Based on code from coreboot
>>>> + */
>>>> +
>>>> +#include <common.h>
>>>> +#include <cpu.h>
>>>> +#include <dm.h>
>>>> +#include <asm/cpu.h>
>>>> +#include <asm/lapic.h>
>>>> +#include <asm/mp.h>
>>>> +#include <asm/msr.h>
>>>> +#include <asm/turbo.h>
>>>> +#include <asm/arch/msr.h>
>>>> +
>>>> +#ifdef CONFIG_SMP
>>>> +static int enable_smis(struct udevice *cpu, void *unused)
>>>> +{
>>>> +       return 0;
>>>> +}
>>>
>>> What is this function for? Is this a must-have?
>>
>> It's partly a placeholder, and also is intended to ensure that the APs
>> are all started before the main CPU continues execution.
>>
>>>
>>>> +
>>>> +static struct mp_flight_record mp_steps[] = {
>>>> +       MP_FR_BLOCK_APS(mp_init_cpu, NULL, mp_init_cpu, NULL),
>>>> +       /* Wait for APs to finish initialization before proceeding. */
>>>> +       MP_FR_BLOCK_APS(NULL, NULL, enable_smis, NULL),
>>>> +};
>>>> +
>>>> +static int detect_num_cpus(void)
>>>> +{
>>>> +       int ecx = 0;
>>>> +
>>>> +       /*
>>>> +        * Use the algorithm described in Intel 64 and IA-32 Architectures
>>>> +        * Software Developer's Manual Volume 3 (3A, 3B & 3C): System
>>>> +        * Programming Guide, Jan-2015. Section 8.9.2: Hierarchical Mapping
>>>> +        * of CPUID Extended Topology Leaf.
>>>> +        */
>>>> +       while (1) {
>>>> +               struct cpuid_result leaf_b;
>>>> +
>>>> +               leaf_b = cpuid_ext(0xb, ecx);
>>>> +
>>>> +               /*
>>>> +                * Bay Trail doesn't have hyperthreading so just determine the
>>>> +                * number of cores by from level type (ecx[15:8] == * 2)
>>>> +                */
>>>> +               if ((leaf_b.ecx & 0xff00) == 0x0200)
>>>> +                       return leaf_b.ebx & 0xffff;
>>>> +               ecx++;
>>>> +       }
>>>> +}
>>>
>>> Since we already describe all cpus in the device tree, is this dynamic
>>> probe really needed?
>>
>> With MinnowMax I'd like to support the single-core version of the
>> board also. It could have its own device tree, but I don't want to
>> break in this case. However, this case is not tested.
>
> Do you mean that there is a specific version of MinnowMax board which
> contains an single core version of Atom E3800 (?, maybe another brand
> name)? But as you said, we can create another device tree for the
> single core version. No? Or maybe we fix up the DTB node here
> dynamically, that we still only have one device tree to describe the
> dual-core version, but after this dynamic probe, we fix up the DTB to
> remove one cpu node if we get a single core version?

Yes that's right. I think we can just mark the second core disabled.
But in the case that it doesn't exist I'd like the code to have the
same effect.

>
>>>
>>>> +
>>>> +static int baytrail_init_cpus(void)
>>>> +{
>>>> +       struct mp_params mp_params;
>>>> +
>>>> +       lapic_setup();
>>>> +
>>>> +       mp_params.num_cpus = detect_num_cpus();
>>>> +       mp_params.parallel_microcode_load = 0,
>>>> +       mp_params.flight_plan = &mp_steps[0];
>>>> +       mp_params.num_records = ARRAY_SIZE(mp_steps);
>>>> +       mp_params.microcode_pointer = 0;
>>>> +
>>>> +       if (mp_init(&mp_params)) {
>>>> +               printf("Warning: MP init failure\n");
>>>> +               return -EIO;
>>>> +       }
>>>> +
>>>> +       return 0;
>>>> +}
>>>> +#endif
>>>> +
>>>> +int x86_init_cpus(void)
>>>> +{
>>>> +#ifdef CONFIG_SMP
>>>> +       debug("Init additional CPUs\n");
>>>> +       baytrail_init_cpus();
>>>> +#endif
>>>> +
>>>> +       return 0;
>>>> +}
>>>> +
>>>> +void set_max_freq(void)
>>>
>>> Should this be static?
>>
>> Yes
>>
>>>
>>>> +{
>>>> +       msr_t perf_ctl;
>>>> +       msr_t msr;
>>>> +
>>>> +       /* Enable speed step */
>>>> +       msr = msr_read(MSR_IA32_MISC_ENABLES);
>>>> +       msr.lo |= (1 << 16);
>>>> +       msr_write(MSR_IA32_MISC_ENABLES, msr);
>>>> +
>>>> +       /*
>>>> +        * Set guaranteed ratio [21:16] from IACORE_RATIOS to bits [15:8] of
>>>> +        * the PERF_CTL
>>>> +        */
>>>> +       msr = msr_read(MSR_IACORE_RATIOS);
>>>> +       perf_ctl.lo = (msr.lo & 0x3f0000) >> 8;
>>>> +
>>>> +       /*
>>>> +        * Set guaranteed vid [21:16] from IACORE_VIDS to bits [7:0] of
>>>> +        * the PERF_CTL
>>>> +        */
>>>> +       msr = msr_read(MSR_IACORE_VIDS);
>>>> +       perf_ctl.lo |= (msr.lo & 0x7f0000) >> 16;
>>>> +       perf_ctl.hi = 0;
>>>> +
>>>> +       msr_write(MSR_IA32_PERF_CTL, perf_ctl);
>>>> +}
>>>> +
>>>> +static int cpu_x86_baytrail_probe(struct udevice *dev)
>>>> +{
>>>> +       debug("Init baytrail core\n");
>>>
>>> BayTrail?
>>
>> OK
>>
>>>
>>>> +
>>>> +       /*
>>>> +        * On bay trail the turbo disable bit is actually scoped at the
>>>
>>> BayTrail?
>>>
>>>> +        * building-block level, not package. For non-BSP cores that are
>>>> +        * within a building block, enable turbo. The cores within the BSP's
>>>> +        * building block will just see it already enabled and move on.
>>>> +        */
>>>> +       if (lapicid())
>>>> +               turbo_enable();
>>>> +
>>>> +       /* Dynamic L2 shrink enable and threshold */
>>>> +       msr_clrsetbits_64(MSR_PMG_CST_CONFIG_CONTROL, 0x3f000f, 0xe0008),
>>>> +
>>>> +       /* Disable C1E */
>>>> +       msr_clrsetbits_64(MSR_POWER_CTL, 2, 0);
>>>> +       msr_setbits_64(MSR_POWER_MISC, 0x44);
>>>> +
>>>> +       /* Set this core to max frequency ratio */
>>>> +       set_max_freq();
>>>> +
>>>> +       return 0;
>>>> +}
>>>> +
>>>> +static unsigned bus_freq(void)
>>>> +{
>>>> +       msr_t clk_info = msr_read(MSR_BSEL_CR_OVERCLOCK_CONTROL);
>>>> +       switch (clk_info.lo & 0x3) {
>>>> +       case 0:
>>>> +               return 83333333;
>>>> +       case 1:
>>>> +               return 100000000;
>>>> +       case 2:
>>>> +               return 133333333;
>>>> +       case 3:
>>>> +               return 116666666;
>>>> +       default:
>>>> +               return 0;
>>>> +       }
>>>> +}
>>>> +
>>>> +static unsigned long tsc_freq(void)
>>>> +{
>>>> +       msr_t platform_info;
>>>> +       ulong bclk = bus_freq();
>>>> +
>>>> +       if (!bclk)
>>>> +               return 0;
>>>> +
>>>> +       platform_info = msr_read(MSR_PLATFORM_INFO);
>>>> +
>>>> +       return bclk * ((platform_info.lo >> 8) & 0xff);
>>>> +}
>>>> +
>>>> +static int baytrail_get_info(struct udevice *dev, struct cpu_info *info)
>>>> +{
>>>> +       info->cpu_freq = tsc_freq();
>>>> +       info->features = 1 << CPU_FEAT_L1_CACHE | 1 << CPU_FEAT_MMU;
>>>> +
>>>> +       return 0;
>>>> +}
>>>> +
>>>> +static int cpu_x86_baytrail_bind(struct udevice *dev)
>>>> +{
>>>> +       struct cpu_platdata *plat = dev_get_parent_platdata(dev);
>>>> +
>>>> +       plat->cpu_id = fdtdec_get_int(gd->fdt_blob, dev->of_offset,
>>>> +                                     "intel,apic-id", -1);
>>>> +
>>>> +       return 0;
>>>> +}
>>>> +
>>>> +static const struct cpu_ops cpu_x86_baytrail_ops = {
>>>> +       .get_desc       = x86_cpu_get_desc,
>>>> +       .get_info       = baytrail_get_info,
>>>> +};
>>>> +
>>>> +static const struct udevice_id cpu_x86_baytrail_ids[] = {
>>>> +       { .compatible = "intel,baytrail-cpu" },
>>>> +       { }
>>>> +};
>>>> +
>>>> +U_BOOT_DRIVER(cpu_x86_baytrail_drv) = {
>>>> +       .name           = "cpu_x86_baytrail",
>>>> +       .id             = UCLASS_CPU,
>>>> +       .of_match       = cpu_x86_baytrail_ids,
>>>> +       .bind           = cpu_x86_baytrail_bind,
>>>> +       .probe          = cpu_x86_baytrail_probe,
>>>> +       .ops            = &cpu_x86_baytrail_ops,
>>>> +};
>>>> diff --git a/arch/x86/include/asm/arch-baytrail/msr.h b/arch/x86/include/asm/arch-baytrail/msr.h
>>>> new file mode 100644
>>>> index 0000000..1975aec
>>>> --- /dev/null
>>>> +++ b/arch/x86/include/asm/arch-baytrail/msr.h
>>>> @@ -0,0 +1,30 @@
>>>> +/*
>>>> + * Copyright (C) 2015 Google, Inc
>>>> + *
>>>> + * SPDX-License-Identifier:    GPL-2.0+
>>>> + */
>>>> +
>>>> +#ifndef __asm_arch_msr_h
>>>> +#define __asm_arch_msr_h
>>>
>>> Should be capital letters, or (see below)
>>>
>>>> +
>>>> +#define MSR_BSEL_CR_OVERCLOCK_CONTROL  0xcd
>>>> +#define MSR_PMG_CST_CONFIG_CONTROL     0xe2
>>>> +#define SINGLE_PCTL                    (1 << 11)
>>>> +#define MSR_POWER_MISC                 0x120
>>>> +#define ENABLE_ULFM_AUTOCM_MASK                (1 << 2)
>>>> +#define ENABLE_INDP_AUTOCM_MASK                (1 << 3)
>>>> +#define MSR_IA32_MISC_ENABLES          0x1a0
>>>> +#define MSR_POWER_CTL                  0x1fc
>>>> +#define MSR_PKG_POWER_SKU_UNIT         0x606
>>>> +#define MSR_IACORE_RATIOS              0x66a
>>>> +#define MSR_IACORE_TURBO_RATIOS                0x66c
>>>> +#define MSR_IACORE_VIDS                        0x66b
>>>> +#define MSR_IACORE_TURBO_VIDS          0x66d
>>>> +#define MSR_PKG_TURBO_CFG1             0x670
>>>> +#define MSR_CPU_TURBO_WKLD_CFG1                0x671
>>>> +#define MSR_CPU_TURBO_WKLD_CFG2                0x672
>>>> +#define MSR_CPU_THERM_CFG1             0x673
>>>> +#define MSR_CPU_THERM_CFG2             0x674
>>>> +#define MSR_CPU_THERM_SENS_CFG         0x675
>>>> +
>>>
>>> Should these be all put into arch/x86/include/asm/msr-index.h, a
>>> single place for all x86 processors' MSR?
>>
>> I was worried that they might be specific to this CPU. But if they are
>> common then yes they should go in the common file.
>>
>
> Maybe some of them are BayTrail-specific. But there MSRs are
> documented in the Intel 64 and IA-32 Architectures Software
> Developer's Manual Volume 3, right? If yes, I think it's fine to put
> them at just one place.

I'll confirm that and move it, thanks.

Regards,
Simon


More information about the U-Boot mailing list