Merge git://git.denx.de/u-boot-x86

This commit is contained in:
Tom Rini 2017-04-10 08:07:29 -04:00
commit 01cce5fdd0
23 changed files with 484 additions and 9 deletions

View file

@ -83,6 +83,8 @@ endchoice
# subarchitectures-specific options below # subarchitectures-specific options below
config INTEL_MID config INTEL_MID
bool "Intel MID platform support" bool "Intel MID platform support"
select REGMAP
select SYSCON
help help
Select to build a U-Boot capable of supporting Intel MID Select to build a U-Boot capable of supporting Intel MID
(Mobile Internet Device) platform systems which do not have (Mobile Internet Device) platform systems which do not have
@ -316,6 +318,22 @@ config X86_RAMTEST
to work correctly. It is not exhaustive but can save time by to work correctly. It is not exhaustive but can save time by
detecting obvious failures. 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 config HAVE_FSP
bool "Add an Firmware Support Package binary" bool "Add an Firmware Support Package binary"
depends on !EFI depends on !EFI

View file

@ -17,8 +17,10 @@
size = <CONFIG_ROM_SIZE>; size = <CONFIG_ROM_SIZE>;
#ifdef CONFIG_HAVE_INTEL_ME #ifdef CONFIG_HAVE_INTEL_ME
intel-descriptor { intel-descriptor {
filename = CONFIG_FLASH_DESCRIPTOR_FILE;
}; };
intel-me { intel-me {
filename = CONFIG_INTEL_ME_FILE;
}; };
#endif #endif
#ifdef CONFIG_SPL #ifdef CONFIG_SPL

View file

@ -54,6 +54,8 @@ enum {
X86_NONE, X86_NONE,
X86_SYSCON_ME, /* Intel Management Engine */ X86_SYSCON_ME, /* Intel Management Engine */
X86_SYSCON_PINCONF, /* Intel x86 pin configuration */ X86_SYSCON_PINCONF, /* Intel x86 pin configuration */
X86_SYSCON_PMU, /* Power Management Unit */
X86_SYSCON_SCU, /* System Controller Unit */
}; };
struct cpuid_result { struct cpuid_result {

View file

@ -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_ */

View file

@ -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_ */

View file

@ -31,7 +31,9 @@ obj-y += pinctrl_ich6.o
obj-y += pirq_routing.o obj-y += pirq_routing.o
obj-y += relocate.o obj-y += relocate.o
obj-y += physmem.o obj-y += physmem.o
obj-$(CONFIG_INTEL_MID) += pmu.o
obj-$(CONFIG_X86_RAMTEST) += ramtest.o obj-$(CONFIG_X86_RAMTEST) += ramtest.o
obj-$(CONFIG_INTEL_MID) += scu.o
obj-y += sections.o obj-y += sections.o
obj-y += sfi.o obj-y += sfi.o
obj-y += string.o obj-y += string.o

View file

@ -100,7 +100,7 @@ static int boot_prep_linux(bootm_headers_t *images)
} }
is_zimage = 1; is_zimage = 1;
#if defined(CONFIG_FIT) #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, ret = fit_image_get_data(images->fit_hdr_os,
images->fit_noffset_os, images->fit_noffset_os,
(const void **)&data, &len); (const void **)&data, &len);

117
arch/x86/lib/pmu.c Normal file
View file

@ -0,0 +1,117 @@
/*
* Copyright (c) 2017 Intel Corporation
*
* SPDX-License-Identifier: GPL-2.0+
*/
#include <common.h>
#include <dm.h>
#include <regmap.h>
#include <syscon.h>
#include <asm/cpu.h>
#include <asm/pmu.h>
#include <linux/errno.h>
#include <linux/io.h>
/* 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(&regs->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(&regs->sss[offset]);
/* Modify PMU values */
if (on)
ssc &= ~(0x3 << shift); /* D0 */
else
ssc |= 0x3 << shift; /* D3hot */
/* Write modified PMU values */
writel(ssc, &regs->ssc[offset]);
/* Update modified PMU values */
writel(0x00002201, &regs->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),
};

168
arch/x86/lib/scu.c Normal file
View file

@ -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 <common.h>
#include <dm.h>
#include <regmap.h>
#include <syscon.h>
#include <asm/cpu.h>
#include <asm/scu.h>
#include <linux/errno.h>
#include <linux/io.h>
#include <linux/kernel.h>
/* 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, &regs->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(&regs->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++, &regs->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(&regs->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),
};

View file

@ -60,6 +60,36 @@ int rtc_write8(struct udevice *dev, unsigned int reg, int val)
return ops->write8(dev, reg, val); return ops->write8(dev, reg, val);
} }
int rtc_read16(struct udevice *dev, unsigned int reg, u16 *valuep)
{
u16 value = 0;
int ret;
int i;
for (i = 0; i < sizeof(value); i++) {
ret = rtc_read8(dev, reg + i);
if (ret < 0)
return ret;
value |= ret << (i << 3);
}
*valuep = value;
return 0;
}
int rtc_write16(struct udevice *dev, unsigned int reg, u16 value)
{
int i, ret;
for (i = 0; i < sizeof(value); i++) {
ret = rtc_write8(dev, reg + i, (value >> (i << 3)) & 0xff);
if (ret)
return ret;
}
return 0;
}
int rtc_read32(struct udevice *dev, unsigned int reg, u32 *valuep) int rtc_read32(struct udevice *dev, unsigned int reg, u32 *valuep)
{ {
u32 value = 0; u32 value = 0;

View file

@ -376,6 +376,15 @@ config SYS_NS16550
be used. It can be a constant or a function to get clock, eg, be used. It can be a constant or a function to get clock, eg,
get_serial_clock(). get_serial_clock().
config INTEL_MID_SERIAL
bool "Intel MID platform UART support"
depends on DM_SERIAL && OF_CONTROL
depends on INTEL_MID
select SYS_NS16550
help
Select this to enable a UART for Intel MID platforms.
This uses the ns16550 driver as a library.
config ROCKCHIP_SERIAL config ROCKCHIP_SERIAL
bool "Rockchip on-chip UART support" bool "Rockchip on-chip UART support"
depends on DM_SERIAL && SPL_OF_PLATDATA depends on DM_SERIAL && SPL_OF_PLATDATA

View file

@ -28,6 +28,7 @@ obj-$(CONFIG_S5P) += serial_s5p.o
obj-$(CONFIG_MXC_UART) += serial_mxc.o obj-$(CONFIG_MXC_UART) += serial_mxc.o
obj-$(CONFIG_PXA_SERIAL) += serial_pxa.o obj-$(CONFIG_PXA_SERIAL) += serial_pxa.o
obj-$(CONFIG_MESON_SERIAL) += serial_meson.o obj-$(CONFIG_MESON_SERIAL) += serial_meson.o
obj-$(CONFIG_INTEL_MID_SERIAL) += serial_intel_mid.o
ifdef CONFIG_SPL_BUILD ifdef CONFIG_SPL_BUILD
obj-$(CONFIG_ROCKCHIP_SERIAL) += serial_rockchip.o obj-$(CONFIG_ROCKCHIP_SERIAL) += serial_rockchip.o
endif endif

View file

@ -0,0 +1,69 @@
/*
* Copyright (c) 2017 Intel Corporation
*
* SPDX-License-Identifier: GPL-2.0+
*/
#include <common.h>
#include <dm.h>
#include <ns16550.h>
#include <serial.h>
/*
* The UART clock is calculated as
*
* UART clock = XTAL * UART_MUL / UART_DIV
*
* The baudrate is calculated as
*
* baud rate = UART clock / UART_PS / DLAB
*/
#define UART_PS 0x30
#define UART_MUL 0x34
#define UART_DIV 0x38
static void mid_writel(struct ns16550_platdata *plat, int offset, int value)
{
unsigned char *addr;
offset *= 1 << plat->reg_shift;
addr = (unsigned char *)plat->base + offset;
writel(value, addr + plat->reg_offset);
}
static int mid_serial_probe(struct udevice *dev)
{
struct ns16550_platdata *plat = dev_get_platdata(dev);
/*
* Initialize fractional divider correctly for Intel Edison
* platform.
*
* For backward compatibility we have to set initial DLAB value
* to 16 and speed to 115200 baud, where initial frequency is
* 29491200Hz, and XTAL frequency is 38.4MHz.
*/
mid_writel(plat, UART_MUL, 96);
mid_writel(plat, UART_DIV, 125);
mid_writel(plat, UART_PS, 16);
return ns16550_serial_probe(dev);
}
static const struct udevice_id mid_serial_ids[] = {
{ .compatible = "intel,mid-uart" },
{}
};
U_BOOT_DRIVER(serial_intel_mid) = {
.name = "serial_intel_mid",
.id = UCLASS_SERIAL,
.of_match = mid_serial_ids,
.ofdata_to_platdata = ns16550_serial_ofdata_to_platdata,
.platdata_auto_alloc_size = sizeof(struct ns16550_platdata),
.priv_auto_alloc_size = sizeof(struct NS16550),
.probe = mid_serial_probe,
.ops = &ns16550_serial_ops,
.flags = DM_FLAG_PRE_RELOC,
};

View file

@ -16,7 +16,6 @@
* (easy to change) * (easy to change)
*/ */
#define CONFIG_SHOW_BOOT_PROGRESS #define CONFIG_SHOW_BOOT_PROGRESS
#define CONFIG_ZBOOT_32
#define CONFIG_PHYSMEM #define CONFIG_PHYSMEM
#define CONFIG_DISPLAY_BOARDINFO_LATE #define CONFIG_DISPLAY_BOARDINFO_LATE
#define CONFIG_LAST_STAGE_INIT #define CONFIG_LAST_STAGE_INIT

View file

@ -127,6 +127,26 @@ int rtc_read8(struct udevice *dev, unsigned int reg);
*/ */
int rtc_write8(struct udevice *dev, unsigned int reg, int val); int rtc_write8(struct udevice *dev, unsigned int reg, int val);
/**
* rtc_read16() - Read a 16-bit value from the RTC
*
* @dev: Device to read from
* @reg: Offset to start reading from
* @valuep: Place to put the value that is read
* @return 0 if OK, -ve on error
*/
int rtc_read16(struct udevice *dev, unsigned int reg, u16 *valuep);
/**
* rtc_write16() - Write a 16-bit value to the RTC
*
* @dev: Device to write to
* @reg: Register to start writing to
* @value: Value to write
* @return 0 if OK, -ve on error
*/
int rtc_write16(struct udevice *dev, unsigned int reg, u16 value);
/** /**
* rtc_read32() - Read a 32-bit value from the RTC * rtc_read32() - Read a 32-bit value from the RTC
* *

View file

@ -6663,7 +6663,6 @@ CONFIG_YAFFS_WINCE
CONFIG_YELLOWSTONE CONFIG_YELLOWSTONE
CONFIG_YELLOW_LED CONFIG_YELLOW_LED
CONFIG_YOSEMITE CONFIG_YOSEMITE
CONFIG_ZBOOT_32
CONFIG_ZC770_XM010 CONFIG_ZC770_XM010
CONFIG_ZC770_XM011 CONFIG_ZC770_XM011
CONFIG_ZC770_XM012 CONFIG_ZC770_XM012

View file

@ -37,9 +37,6 @@ class Entry_intel_descriptor(Entry_blob):
Entry_blob.__init__(self, image, etype, node) Entry_blob.__init__(self, image, etype, node)
self._regions = [] self._regions = []
def GetDefaultFilename(self):
return 'descriptor.bin'
def GetPositions(self): def GetPositions(self):
pos = self.data.find(FD_SIGNATURE) pos = self.data.find(FD_SIGNATURE)
if pos == -1: if pos == -1:

View file

@ -12,6 +12,3 @@ from blob import Entry_blob
class Entry_intel_me(Entry_blob): class Entry_intel_me(Entry_blob):
def __init__(self, image, etype, node): def __init__(self, image, etype, node):
Entry_blob.__init__(self, image, etype, node) Entry_blob.__init__(self, image, etype, node)
def GetDefaultFilename(self):
return 'me.bin'

View file

@ -9,6 +9,7 @@
end-at-4gb; end-at-4gb;
size = <16>; size = <16>;
intel-me { intel-me {
filename = "me.bin";
pos-unset; pos-unset;
}; };
}; };

View file

@ -9,9 +9,11 @@
end-at-4gb; end-at-4gb;
size = <0x800000>; size = <0x800000>;
intel-descriptor { intel-descriptor {
filename = "descriptor.bin";
}; };
intel-me { intel-me {
filename = "me.bin";
pos-unset; pos-unset;
}; };
}; };

View file

@ -8,6 +8,7 @@
size = <16>; size = <16>;
intel-vga { intel-vga {
filename = "vga.bin";
}; };
}; };
}; };

View file

@ -8,6 +8,7 @@
size = <16>; size = <16>;
intel-fsp { intel-fsp {
filename = "fsp.bin";
}; };
}; };
}; };

View file

@ -8,6 +8,7 @@
size = <16>; size = <16>;
intel-cmc { intel-cmc {
filename = "cmc.bin";
}; };
}; };
}; };