From 3dc0f8446aae39256c2259e948251e68f106919b Mon Sep 17 00:00:00 2001 From: Stefan Roese Date: Thu, 30 Mar 2017 12:58:10 +0200 Subject: x86: Kconfig: Add options to configure the descriptor.bin / me.bin filenames This introduces two Kconfig options to enable board specific filenames for the Intel binary blobs to be used to generate the SPI flash image. Signed-off-by: Stefan Roese Cc: Bin Meng Cc: Simon Glass Reviewed-by: Bin Meng --- arch/x86/Kconfig | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'arch') diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index dfdd7564ea0..6ce127a23c1 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -316,6 +316,22 @@ config X86_RAMTEST to work correctly. It is not exhaustive but can save time by detecting obvious failures. +config FLASH_DESCRIPTOR_FILE + string "Flash descriptor binary filename" + depends on HAVE_INTEL_ME + default "descriptor.bin" + help + The filename of the file to use as flash descriptor in the + board directory. + +config INTEL_ME_FILE + string "Intel Management Engine binary filename" + depends on HAVE_INTEL_ME + default "me.bin" + help + The filename of the file to use as Intel Management Engine in the + board directory. + config HAVE_FSP bool "Add an Firmware Support Package binary" depends on !EFI -- cgit v1.3.1 From cccab03a529ac1bf1a66ff75fb15784005ec8570 Mon Sep 17 00:00:00 2001 From: Stefan Roese Date: Thu, 30 Mar 2017 12:58:11 +0200 Subject: x86: Add file names from Kconfig in descriptor/intel-me nodes in u-boot.dtsi Since we now have the file names configurable via Kconfig for the flash descriptor and intel-me files, add these from Kconfig in the corresponding dts nodes. Signed-off-by: Stefan Roese Cc: Bin Meng Cc: Simon Glass Reviewed-by: Bin Meng --- arch/x86/dts/u-boot.dtsi | 2 ++ 1 file changed, 2 insertions(+) (limited to 'arch') diff --git a/arch/x86/dts/u-boot.dtsi b/arch/x86/dts/u-boot.dtsi index 69c1c1d4986..a4321d33de5 100644 --- a/arch/x86/dts/u-boot.dtsi +++ b/arch/x86/dts/u-boot.dtsi @@ -17,8 +17,10 @@ size = ; #ifdef CONFIG_HAVE_INTEL_ME intel-descriptor { + filename = CONFIG_FLASH_DESCRIPTOR_FILE; }; intel-me { + filename = CONFIG_INTEL_ME_FILE; }; #endif #ifdef CONFIG_SPL -- cgit v1.3.1 From 13c531e52a09b4e6ffa8b5a1457199b0a574cb27 Mon Sep 17 00:00:00 2001 From: Stefan Roese Date: Fri, 31 Mar 2017 08:09:39 +0200 Subject: x86: bootm: Fix FIT image booting on x86 Checking 'is_zimage' at this time will always fail and therefore booting a FIT style image will always lead to this error message: "## Kernel loading failed (missing x86 kernel setup) ..." This change now removes this check and booting of FIT images works just fine. Signed-off-by: Stefan Roese Cc: Simon Glass Cc: Bin Meng Reviewed-by: Simon Glass Reviewed-by: Bin Meng --- arch/x86/lib/bootm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/x86/lib/bootm.c b/arch/x86/lib/bootm.c index 3c3d9e1e800..75bab902251 100644 --- a/arch/x86/lib/bootm.c +++ b/arch/x86/lib/bootm.c @@ -100,7 +100,7 @@ static int boot_prep_linux(bootm_headers_t *images) } is_zimage = 1; #if defined(CONFIG_FIT) - } else if (images->fit_uname_os && is_zimage) { + } else if (images->fit_uname_os) { ret = fit_image_get_data(images->fit_hdr_os, images->fit_noffset_os, (const void **)&data, &len); -- cgit v1.3.1 From bb416465fde8393bcbf1f64847b5e3cb021d5c81 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Sat, 1 Apr 2017 16:21:33 +0300 Subject: x86: Add SCU IPC driver for Intel MID platforms Intel MID platforms have few microcontrollers inside SoC, one of them is so called System Controller Unit (SCU). Here is the driver to communicate with microcontroller. Signed-off-by: Vincent Tinelli Signed-off-by: Felipe Balbi Signed-off-by: Andy Shevchenko Acked-by: Simon Glass --- arch/x86/Kconfig | 2 + arch/x86/include/asm/cpu.h | 1 + arch/x86/include/asm/scu.h | 28 ++++++++ arch/x86/lib/Makefile | 1 + arch/x86/lib/scu.c | 168 +++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 200 insertions(+) create mode 100644 arch/x86/include/asm/scu.h create mode 100644 arch/x86/lib/scu.c (limited to 'arch') diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 6ce127a23c1..9ead3ebccf8 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -83,6 +83,8 @@ endchoice # subarchitectures-specific options below config INTEL_MID bool "Intel MID platform support" + select REGMAP + select SYSCON help Select to build a U-Boot capable of supporting Intel MID (Mobile Internet Device) platform systems which do not have diff --git a/arch/x86/include/asm/cpu.h b/arch/x86/include/asm/cpu.h index c651f2f5945..0ee13b1eb16 100644 --- a/arch/x86/include/asm/cpu.h +++ b/arch/x86/include/asm/cpu.h @@ -54,6 +54,7 @@ enum { X86_NONE, X86_SYSCON_ME, /* Intel Management Engine */ X86_SYSCON_PINCONF, /* Intel x86 pin configuration */ + X86_SYSCON_SCU, /* System Controller Unit */ }; struct cpuid_result { diff --git a/arch/x86/include/asm/scu.h b/arch/x86/include/asm/scu.h new file mode 100644 index 00000000000..4d40e495bb7 --- /dev/null +++ b/arch/x86/include/asm/scu.h @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2017 Intel Corporation + * + * SPDX-License-Identifier: GPL-2.0+ + */ +#ifndef _X86_ASM_SCU_IPC_H_ +#define _X86_ASM_SCU_IPC_H_ + +/* IPC defines the following message types */ +#define IPCMSG_WARM_RESET 0xf0 +#define IPCMSG_COLD_RESET 0xf1 +#define IPCMSG_SOFT_RESET 0xf2 +#define IPCMSG_COLD_BOOT 0xf3 +#define IPCMSG_GET_FW_REVISION 0xf4 +#define IPCMSG_WATCHDOG_TIMER 0xf8 /* Set Kernel Watchdog Threshold */ + +struct ipc_ifwi_version { + u16 minor; + u8 major; + u8 hardware_id; + u32 reserved[3]; +}; + +/* Issue commands to the SCU with or without data */ +int scu_ipc_simple_command(u32 cmd, u32 sub); +int scu_ipc_command(u32 cmd, u32 sub, u32 *in, int inlen, u32 *out, int outlen); + +#endif /* _X86_ASM_SCU_IPC_H_ */ diff --git a/arch/x86/lib/Makefile b/arch/x86/lib/Makefile index 1c2c0851790..320e45e4a06 100644 --- a/arch/x86/lib/Makefile +++ b/arch/x86/lib/Makefile @@ -32,6 +32,7 @@ obj-y += pirq_routing.o obj-y += relocate.o obj-y += physmem.o obj-$(CONFIG_X86_RAMTEST) += ramtest.o +obj-$(CONFIG_INTEL_MID) += scu.o obj-y += sections.o obj-y += sfi.o obj-y += string.o diff --git a/arch/x86/lib/scu.c b/arch/x86/lib/scu.c new file mode 100644 index 00000000000..bb23d0b829e --- /dev/null +++ b/arch/x86/lib/scu.c @@ -0,0 +1,168 @@ +/* + * Copyright (c) 2017 Intel Corporation + * + * Intel Mobile Internet Devices (MID) based on Intel Atom SoCs have few + * microcontrollers inside to do some auxiliary tasks. One of such + * microcontroller is System Controller Unit (SCU) which, in particular, + * is servicing watchdog and controlling system reset function. + * + * This driver enables IPC channel to SCU. + * + * SPDX-License-Identifier: GPL-2.0+ + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* SCU register map */ +struct ipc_regs { + u32 cmd; + u32 status; + u32 sptr; + u32 dptr; + u32 reserved[28]; + u32 wbuf[4]; + u32 rbuf[4]; +}; + +struct scu { + struct ipc_regs *regs; +}; + +/** + * scu_ipc_send_command() - send command to SCU + * @regs: register map of SCU + * @cmd: command + * + * Command Register (Write Only): + * A write to this register results in an interrupt to the SCU core processor + * Format: + * |rfu2(8) | size(8) | command id(4) | rfu1(3) | ioc(1) | command(8)| + */ +static void scu_ipc_send_command(struct ipc_regs *regs, u32 cmd) +{ + writel(cmd, ®s->cmd); +} + +/** + * scu_ipc_check_status() - check status of last command + * @regs: register map of SCU + * + * Status Register (Read Only): + * Driver will read this register to get the ready/busy status of the IPC + * block and error status of the IPC command that was just processed by SCU + * Format: + * |rfu3(8)|error code(8)|initiator id(8)|cmd id(4)|rfu1(2)|error(1)|busy(1)| + */ +static int scu_ipc_check_status(struct ipc_regs *regs) +{ + int loop_count = 100000; + int status; + + do { + status = readl(®s->status); + if (!(status & BIT(0))) + break; + + udelay(1); + } while (--loop_count); + if (!loop_count) + return -ETIMEDOUT; + + if (status & BIT(1)) { + printf("%s() status=0x%08x\n", __func__, status); + return -EIO; + } + + return 0; +} + +static int scu_ipc_cmd(struct ipc_regs *regs, u32 cmd, u32 sub, + u32 *in, int inlen, u32 *out, int outlen) +{ + int i, err; + + for (i = 0; i < inlen; i++) + writel(*in++, ®s->wbuf[i]); + + scu_ipc_send_command(regs, (inlen << 16) | (sub << 12) | cmd); + err = scu_ipc_check_status(regs); + + if (!err) { + for (i = 0; i < outlen; i++) + *out++ = readl(®s->rbuf[i]); + } + + return err; +} + +/** + * scu_ipc_simple_command() - send a simple command + * @cmd: command + * @sub: sub type + * + * Issue a simple command to the SCU. Do not use this interface if + * you must then access data as any data values may be overwritten + * by another SCU access by the time this function returns. + * + * This function may sleep. Locking for SCU accesses is handled for + * the caller. + */ +int scu_ipc_simple_command(u32 cmd, u32 sub) +{ + struct scu *scu; + struct udevice *dev; + int ret; + + ret = syscon_get_by_driver_data(X86_SYSCON_SCU, &dev); + if (ret) + return ret; + + scu = dev_get_priv(dev); + + scu_ipc_send_command(scu->regs, sub << 12 | cmd); + return scu_ipc_check_status(scu->regs); +} + +int scu_ipc_command(u32 cmd, u32 sub, u32 *in, int inlen, u32 *out, int outlen) +{ + struct scu *scu; + struct udevice *dev; + int ret; + + ret = syscon_get_by_driver_data(X86_SYSCON_SCU, &dev); + if (ret) + return ret; + + scu = dev_get_priv(dev); + + return scu_ipc_cmd(scu->regs, cmd, sub, in, inlen, out, outlen); +} + +static int scu_ipc_probe(struct udevice *dev) +{ + struct scu *scu = dev_get_priv(dev); + + scu->regs = syscon_get_first_range(X86_SYSCON_SCU); + + return 0; +} + +static const struct udevice_id scu_ipc_match[] = { + { .compatible = "intel,scu-ipc", .data = X86_SYSCON_SCU }, + { /* sentinel */ } +}; + +U_BOOT_DRIVER(scu_ipc) = { + .name = "scu_ipc", + .id = UCLASS_SYSCON, + .of_match = scu_ipc_match, + .probe = scu_ipc_probe, + .priv_auto_alloc_size = sizeof(struct scu), +}; -- cgit v1.3.1 From ca0d29e4f06095fd39f3125aef8f427aa1728ee5 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Sat, 1 Apr 2017 16:21:34 +0300 Subject: x86: Introduce minimal PMU driver for Intel MID platforms This simple PMU driver allows to tyrn power on and off for selected devices. In particularly Intel Tangier needs to power on SDHCI controllers in order to access to them during board initialization. In the future it might be expanded to cover other Intel MID platforms, that's why it's located under arch/x86/lib and called pmu.c. Signed-off-by: Felipe Balbi Signed-off-by: Andy Shevchenko Reviewed-by: Simon Glass --- arch/x86/include/asm/cpu.h | 1 + arch/x86/include/asm/pmu.h | 11 +++++ arch/x86/lib/Makefile | 1 + arch/x86/lib/pmu.c | 117 +++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 130 insertions(+) create mode 100644 arch/x86/include/asm/pmu.h create mode 100644 arch/x86/lib/pmu.c (limited to 'arch') diff --git a/arch/x86/include/asm/cpu.h b/arch/x86/include/asm/cpu.h index 0ee13b1eb16..c00687a20af 100644 --- a/arch/x86/include/asm/cpu.h +++ b/arch/x86/include/asm/cpu.h @@ -54,6 +54,7 @@ enum { X86_NONE, X86_SYSCON_ME, /* Intel Management Engine */ X86_SYSCON_PINCONF, /* Intel x86 pin configuration */ + X86_SYSCON_PMU, /* Power Management Unit */ X86_SYSCON_SCU, /* System Controller Unit */ }; diff --git a/arch/x86/include/asm/pmu.h b/arch/x86/include/asm/pmu.h new file mode 100644 index 00000000000..96b968ff8fd --- /dev/null +++ b/arch/x86/include/asm/pmu.h @@ -0,0 +1,11 @@ +/* + * Copyright (c) 2017 Intel Corporation + * + * SPDX-License-Identifier: GPL-2.0+ + */ +#ifndef _X86_ASM_PMU_IPC_H_ +#define _X86_ASM_PMU_IPC_H_ + +int pmu_turn_power(unsigned int lss, bool on); + +#endif /* _X86_ASM_PMU_IPC_H_ */ diff --git a/arch/x86/lib/Makefile b/arch/x86/lib/Makefile index 320e45e4a06..d1ad37af648 100644 --- a/arch/x86/lib/Makefile +++ b/arch/x86/lib/Makefile @@ -31,6 +31,7 @@ obj-y += pinctrl_ich6.o obj-y += pirq_routing.o obj-y += relocate.o obj-y += physmem.o +obj-$(CONFIG_INTEL_MID) += pmu.o obj-$(CONFIG_X86_RAMTEST) += ramtest.o obj-$(CONFIG_INTEL_MID) += scu.o obj-y += sections.o diff --git a/arch/x86/lib/pmu.c b/arch/x86/lib/pmu.c new file mode 100644 index 00000000000..4ceab8dc640 --- /dev/null +++ b/arch/x86/lib/pmu.c @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2017 Intel Corporation + * + * SPDX-License-Identifier: GPL-2.0+ + */ +#include +#include +#include +#include +#include +#include +#include +#include + +/* Registers */ +struct pmu_regs { + u32 sts; + u32 cmd; + u32 ics; + u32 reserved; + u32 wkc[4]; + u32 wks[4]; + u32 ssc[4]; + u32 sss[4]; +}; + +/* Bits in PMU_REGS_STS */ +#define PMU_REGS_STS_BUSY (1 << 8) + +struct pmu_mid { + struct pmu_regs *regs; +}; + +static int pmu_read_status(struct pmu_regs *regs) +{ + int retry = 500000; + u32 val; + + do { + val = readl(®s->sts); + if (!(val & PMU_REGS_STS_BUSY)) + return 0; + + udelay(1); + } while (--retry); + + printf("WARNING: PMU still busy\n"); + return -EBUSY; +} + +static int pmu_power_lss(struct pmu_regs *regs, unsigned int lss, bool on) +{ + unsigned int offset = (lss * 2) / 32; + unsigned int shift = (lss * 2) % 32; + u32 ssc; + int ret; + + /* Check PMU status */ + ret = pmu_read_status(regs); + if (ret) + return ret; + + /* Read PMU values */ + ssc = readl(®s->sss[offset]); + + /* Modify PMU values */ + if (on) + ssc &= ~(0x3 << shift); /* D0 */ + else + ssc |= 0x3 << shift; /* D3hot */ + + /* Write modified PMU values */ + writel(ssc, ®s->ssc[offset]); + + /* Update modified PMU values */ + writel(0x00002201, ®s->cmd); + + /* Check PMU status */ + return pmu_read_status(regs); +} + +int pmu_turn_power(unsigned int lss, bool on) +{ + struct pmu_mid *pmu; + struct udevice *dev; + int ret; + + ret = syscon_get_by_driver_data(X86_SYSCON_PMU, &dev); + if (ret) + return ret; + + pmu = dev_get_priv(dev); + + return pmu_power_lss(pmu->regs, lss, on); +} + +static int pmu_mid_probe(struct udevice *dev) +{ + struct pmu_mid *pmu = dev_get_priv(dev); + + pmu->regs = syscon_get_first_range(X86_SYSCON_PMU); + + return 0; +} + +static const struct udevice_id pmu_mid_match[] = { + { .compatible = "intel,pmu-mid", .data = X86_SYSCON_PMU }, + { /* sentinel */ } +}; + +U_BOOT_DRIVER(intel_mid_pmu) = { + .name = "pmu_mid", + .id = UCLASS_SYSCON, + .of_match = pmu_mid_match, + .probe = pmu_mid_probe, + .priv_auto_alloc_size = sizeof(struct pmu_mid), +}; -- cgit v1.3.1