Merge branch 'master' of git://git.denx.de/u-boot

This commit is contained in:
Stefano Babic 2015-07-17 11:22:56 +02:00
commit f448c5d320
133 changed files with 2537 additions and 1764 deletions

10
MAKEALL
View file

@ -60,6 +60,14 @@ usage()
exit ${ret}
}
deprecation() {
echo "** Note: MAKEALL is deprecated - please use buildman instead"
echo "** See tools/buildman/README for details"
echo
}
deprecation
SHORT_OPTS="ha:c:v:s:b:lmMCnr"
LONG_OPTS="help,arch:,cpu:,vendor:,soc:,board:,list,maintainers,mails,check,continue,rebuild-errors"
@ -827,6 +835,8 @@ print_stats() {
kill_children
fi
deprecation
exit $RC
}

View file

@ -1,7 +1,7 @@
VERSION = 2015
PATCHLEVEL = 07
SUBLEVEL =
EXTRAVERSION = -rc3
EXTRAVERSION =
NAME =
# *DOCUMENTATION*
@ -565,6 +565,7 @@ KBUILD_CFLAGS += -DBUILD_TAG='"$(BUILD_TAG)"'
endif
KBUILD_CFLAGS += $(call cc-option,-fno-stack-protector)
KBUILD_CFLAGS += $(call cc-option,-fno-delete-null-pointer-checks)
KBUILD_CFLAGS += -g
# $(KBUILD_AFLAGS) sets -g, which causes gcc to pass a suitable -g<format>
@ -1034,8 +1035,8 @@ ifneq ($(CONFIG_HAVE_CMC),)
IFDTOOL_FLAGS += -w $(CONFIG_CMC_ADDR):$(srctree)/board/$(BOARDDIR)/$(CONFIG_CMC_FILE)
endif
ifneq ($(CONFIG_X86_OPTION_ROM_ADDR),)
IFDTOOL_FLAGS += -w $(CONFIG_X86_OPTION_ROM_ADDR):$(srctree)/board/$(BOARDDIR)/$(CONFIG_X86_OPTION_ROM_FILE)
ifneq ($(CONFIG_HAVE_VGA_BIOS),)
IFDTOOL_FLAGS += -w $(CONFIG_VGA_BIOS_ADDR):$(srctree)/board/$(BOARDDIR)/$(CONFIG_VGA_BIOS_FILE)
endif
quiet_cmd_ifdtool = IFDTOOL $@

View file

@ -227,6 +227,9 @@ config TARGET_STV0991
select CPU_V7
select DM
select DM_SERIAL
select DM_SPI
select DM_SPI_FLASH
select SPI_FLASH
config TARGET_X600
bool "Support x600"

View file

@ -33,7 +33,9 @@ void clock_setup(int peripheral)
/* Clock selection for ethernet tx_clk & rx_clk*/
writel((readl(&stv0991_cgu_regs->eth_ctrl) & ETH_CLK_MASK)
| ETH_CLK_CTRL, &stv0991_cgu_regs->eth_ctrl);
break;
case QSPI_CLOCK_CFG:
writel(QSPI_CLK_CTRL, &stv0991_cgu_regs->qspi_freq);
break;
default:
break;

View file

@ -55,6 +55,11 @@ int stv0991_pinmux_config(int peripheral)
ETH_M_VDD_CFG, &stv0991_creg->vdd_pad1);
break;
case QSPI_CS_CLK_PAD:
writel((readl(&stv0991_creg->mux13) & FLASH_CS_NC_MASK) |
CFG_FLASH_CS_NC, &stv0991_creg->mux13);
writel((readl(&stv0991_creg->mux13) & FLASH_CLK_MASK) |
CFG_FLASH_CLK, &stv0991_creg->mux13);
default:
break;
}

View file

@ -639,6 +639,7 @@
ext-decoder = <0>; /* external decoder */
num-cs = <4>;
fifo-depth = <128>;
sram-size = <128>;
bus-num = <2>;
status = "disabled";
};

View file

@ -20,4 +20,34 @@
reg = <0x80406000 0x1000>;
clock = <2700000>;
};
aliases {
spi0 = "/spi@80203000"; /* QSPI */
};
qspi: spi@80203000 {
compatible = "cadence,qspi";
#address-cells = <1>;
#size-cells = <0>;
reg = <0x80203000 0x100>,
<0x40000000 0x1000000>;
clocks = <3750000>;
sram-size = <256>;
status = "okay";
flash0: n25q32@0 {
#address-cells = <1>;
#size-cells = <1>;
compatible = "spi-flash";
reg = <0>; /* chip select */
spi-max-frequency = <50000000>;
m25p,fast-read;
page-size = <256>;
block-size = <16>; /* 2^16, 64KB */
tshsl-ns = <50>;
tsd2d-ns = <50>;
tchsh-ns = <4>;
tslch-ns = <4>;
};
};
};

View file

@ -113,4 +113,19 @@ struct stv0991_cgu_regs {
#define ETH_CLK_CTRL (ETH_CLK_RX_EXT_PHY << RX_CLK_SHIFT \
| ETH_CLK_TX_EXT_PHY)
/* CGU qspi clock */
#define DIV_HCLK1_SHIFT 9
#define DIV_CRYP_SHIFT 6
#define MDIV_QSPI_SHIFT 3
#define CLK_QSPI_OSC 0
#define CLK_QSPI_MCLK 1
#define CLK_QSPI_PLL1 2
#define CLK_QSPI_PLL2 3
#define QSPI_CLK_CTRL (3 << DIV_HCLK1_SHIFT \
| 1 << DIV_CRYP_SHIFT \
| 0 << MDIV_QSPI_SHIFT \
| CLK_QSPI_OSC)
#endif

View file

@ -49,6 +49,15 @@ struct stv0991_creg {
u32 vdd_comp1; /* offset 0x400 */
};
/* CREG MUX 13 register */
#define FLASH_CS_NC_SHIFT 4
#define FLASH_CS_NC_MASK ~(7 << FLASH_CS_NC_SHIFT)
#define CFG_FLASH_CS_NC (0 << FLASH_CS_NC_SHIFT)
#define FLASH_CLK_SHIFT 0
#define FLASH_CLK_MASK ~(7 << FLASH_CLK_SHIFT)
#define CFG_FLASH_CLK (0 << FLASH_CLK_SHIFT)
/* CREG MUX 12 register */
#define GPIOC_30_MUX_SHIFT 24
#define GPIOC_30_MUX_MASK ~(1 << GPIOC_30_MUX_SHIFT)

View file

@ -18,6 +18,7 @@ enum periph_id {
UART_GPIOC_30_31 = 0,
UART_GPIOB_16_17,
ETH_GPIOB_10_31_C_0_4,
QSPI_CS_CLK_PAD,
PERIPH_ID_I2C0,
PERIPH_ID_I2C1,
PERIPH_ID_I2C2,
@ -39,6 +40,7 @@ enum periph_id {
enum periph_clock {
UART_CLOCK_CFG = 0,
ETH_CLOCK_CFG,
QSPI_CLOCK_CFG,
};
#endif /* __ASM_ARM_ARCH_PERIPH_H */

View file

@ -6,10 +6,13 @@
#include <common.h>
#include <netdev.h>
#include <ahci.h>
#include <linux/mbus.h>
#include <asm/io.h>
#include <asm/pl310.h>
#include <asm/arch/cpu.h>
#include <asm/arch/soc.h>
#include <sdhci.h>
#define DDR_BASE_CS_OFF(n) (0x0000 + ((n) << 3))
#define DDR_SIZE_CS_OFF(n) (0x0004 + ((n) << 3))
@ -245,6 +248,69 @@ int cpu_eth_init(bd_t *bis)
}
#endif
#ifdef CONFIG_MV_SDHCI
int board_mmc_init(bd_t *bis)
{
mv_sdh_init(MVEBU_SDIO_BASE, 0, 0,
SDHCI_QUIRK_32BIT_DMA_ADDR | SDHCI_QUIRK_WAIT_SEND_CMD);
return 0;
}
#endif
#ifdef CONFIG_SCSI_AHCI_PLAT
#define AHCI_VENDOR_SPECIFIC_0_ADDR 0xa0
#define AHCI_VENDOR_SPECIFIC_0_DATA 0xa4
#define AHCI_WINDOW_CTRL(win) (0x60 + ((win) << 4))
#define AHCI_WINDOW_BASE(win) (0x64 + ((win) << 4))
#define AHCI_WINDOW_SIZE(win) (0x68 + ((win) << 4))
static void ahci_mvebu_mbus_config(void __iomem *base)
{
const struct mbus_dram_target_info *dram;
int i;
dram = mvebu_mbus_dram_info();
for (i = 0; i < 4; i++) {
writel(0, base + AHCI_WINDOW_CTRL(i));
writel(0, base + AHCI_WINDOW_BASE(i));
writel(0, base + AHCI_WINDOW_SIZE(i));
}
for (i = 0; i < dram->num_cs; i++) {
const struct mbus_dram_window *cs = dram->cs + i;
writel((cs->mbus_attr << 8) |
(dram->mbus_dram_target_id << 4) | 1,
base + AHCI_WINDOW_CTRL(i));
writel(cs->base >> 16, base + AHCI_WINDOW_BASE(i));
writel(((cs->size - 1) & 0xffff0000),
base + AHCI_WINDOW_SIZE(i));
}
}
static void ahci_mvebu_regret_option(void __iomem *base)
{
/*
* Enable the regret bit to allow the SATA unit to regret a
* request that didn't receive an acknowlegde and avoid a
* deadlock
*/
writel(0x4, base + AHCI_VENDOR_SPECIFIC_0_ADDR);
writel(0x80, base + AHCI_VENDOR_SPECIFIC_0_DATA);
}
void scsi_init(void)
{
printf("MVEBU SATA INIT\n");
ahci_mvebu_mbus_config((void __iomem *)MVEBU_SATA0_BASE);
ahci_mvebu_regret_option((void __iomem *)MVEBU_SATA0_BASE);
ahci_init((void __iomem *)MVEBU_SATA0_BASE);
}
#endif
#ifndef CONFIG_SYS_DCACHE_OFF
void enable_caches(void)
{

View file

@ -114,6 +114,8 @@ void mvebu_sdram_size_adjust(enum memory_bank bank);
int mvebu_mbus_probe(struct mbus_win windows[], int count);
int mvebu_soc_family(void);
int mv_sdh_init(unsigned long regbase, u32 max_clk, u32 min_clk, u32 quirks);
/*
* Highspeed SERDES PHY config init, ported from bin_hdr
* to mainline U-Boot

View file

@ -0,0 +1,10 @@
/*
* SPDX-License-Identifier: GPL-2.0+
*/
#ifndef __MACH_MVEBU_GPIO_H
#define __MACH_MVEBU_GPIO_H
/* Empty file - sdhci requires this. */
#endif

View file

@ -49,8 +49,11 @@
#define MVEBU_EGIGA2_BASE (MVEBU_REGISTER(0x30000))
#define MVEBU_EGIGA3_BASE (MVEBU_REGISTER(0x34000))
#define MVEBU_REG_PCIE_BASE (MVEBU_REGISTER(0x40000))
#define MVEBU_USB20_BASE (MVEBU_REGISTER(0x58000))
#define MVEBU_EGIGA0_BASE (MVEBU_REGISTER(0x70000))
#define MVEBU_EGIGA1_BASE (MVEBU_REGISTER(0x74000))
#define MVEBU_SATA0_BASE (MVEBU_REGISTER(0xa8000))
#define MVEBU_SDIO_BASE (MVEBU_REGISTER(0xd8000))
#define SDRAM_MAX_CS 4
#define SDRAM_ADDR_MASK 0xFF000000

View file

@ -18,7 +18,7 @@ static inline void mips_cache(int op, const volatile void *addr)
#ifdef __GCC_HAVE_BUILTIN_MIPS_CACHE
__builtin_mips_cache(op, addr);
#else
__asm__ __volatile__("cache %0, %1" : : "i"(op), "R"(addr))
__asm__ __volatile__("cache %0, %1" : : "i"(op), "R"(addr));
#endif
}

View file

@ -117,7 +117,7 @@ static inline void set_io_port_base(unsigned long base)
* Change virtual addresses to physical addresses and vv.
* These are trivial on the 1:1 Linux/MIPS mapping
*/
extern inline phys_addr_t virt_to_phys(volatile void * address)
static inline phys_addr_t virt_to_phys(volatile void * address)
{
#ifndef CONFIG_64BIT
return CPHYSADDR(address);
@ -126,7 +126,7 @@ extern inline phys_addr_t virt_to_phys(volatile void * address)
#endif
}
extern inline void * phys_to_virt(unsigned long address)
static inline void * phys_to_virt(unsigned long address)
{
#ifndef CONFIG_64BIT
return (void *)KSEG0ADDR(address);
@ -138,7 +138,7 @@ extern inline void * phys_to_virt(unsigned long address)
/*
* IO bus memory addresses are also 1:1 with the physical address
*/
extern inline unsigned long virt_to_bus(volatile void * address)
static inline unsigned long virt_to_bus(volatile void * address)
{
#ifndef CONFIG_64BIT
return CPHYSADDR(address);
@ -147,7 +147,7 @@ extern inline unsigned long virt_to_bus(volatile void * address)
#endif
}
extern inline void * bus_to_virt(unsigned long address)
static inline void * bus_to_virt(unsigned long address)
{
#ifndef CONFIG_64BIT
return (void *)KSEG0ADDR(address);
@ -165,12 +165,12 @@ extern unsigned long isa_slot_offset;
extern void * __ioremap(unsigned long offset, unsigned long size, unsigned long flags);
#if 0
extern inline void *ioremap(unsigned long offset, unsigned long size)
static inline void *ioremap(unsigned long offset, unsigned long size)
{
return __ioremap(offset, size, _CACHE_UNCACHED);
}
extern inline void *ioremap_nocache(unsigned long offset, unsigned long size)
static inline void *ioremap_nocache(unsigned long offset, unsigned long size)
{
return __ioremap(offset, size, _CACHE_UNCACHED);
}

View file

@ -22,7 +22,7 @@
#include <linux/kernel.h>
#endif
extern __inline__ void
static __inline__ void
__sti(void)
{
__asm__ __volatile__(
@ -46,7 +46,7 @@ __sti(void)
* R4000/R4400 need three nops, the R4600 two nops and the R10000 needs
* no nops at all.
*/
extern __inline__ void
static __inline__ void
__cli(void)
{
__asm__ __volatile__(
@ -207,7 +207,7 @@ do { \
* For 32 and 64 bit operands we can take advantage of ll and sc.
* FIXME: This doesn't work for R3000 machines.
*/
extern __inline__ unsigned long xchg_u32(volatile int * m, unsigned long val)
static __inline__ unsigned long xchg_u32(volatile int * m, unsigned long val)
{
#ifdef CONFIG_CPU_HAS_LLSC
unsigned long dummy;

View file

@ -69,6 +69,21 @@ config X86_RESET_VECTOR
bool
default n
config RESET_SEG_START
hex
depends on X86_RESET_VECTOR
default 0xffff0000
config RESET_SEG_SIZE
hex
depends on X86_RESET_VECTOR
default 0x10000
config RESET_VEC_LOC
hex
depends on X86_RESET_VECTOR
default 0xfffffff0
config SYS_X86_START16
hex
depends on X86_RESET_VECTOR
@ -173,14 +188,6 @@ config X86_RAMTEST
to work correctly. It is not exhaustive but can save time by
detecting obvious failures.
config MARK_GRAPHICS_MEM_WRCOMB
bool "Mark graphics memory as write-combining"
default n
help
The graphics performance may increase if the graphics
memory is set as write-combining cache type. This option
enables marking the graphics memory as write-combining.
config HAVE_FSP
bool "Add an Firmware Support Package binary"
help
@ -220,17 +227,6 @@ config FSP_TEMP_RAM_ADDR
Stack top address which is used in FspInit after DRAM is ready and
CAR is disabled.
config MAX_CPUS
int "Maximum number of CPUs permitted"
default 4
help
When using multi-CPU chips it is possible for U-Boot to start up
more than one CPU. The stack memory used by all of these CPUs is
pre-allocated so at present U-Boot wants to know the maximum
number of CPUs that may be present. Set this to at least as high
as the number of CPUs in your system (it uses about 4KB of RAM for
each CPU).
config SMP
bool "Enable Symmetric Multiprocessing"
default n
@ -241,8 +237,21 @@ config SMP
only one CPU will be enabled regardless of the number of CPUs
available.
config MAX_CPUS
int "Maximum number of CPUs permitted"
depends on SMP
default 4
help
When using multi-CPU chips it is possible for U-Boot to start up
more than one CPU. The stack memory used by all of these CPUs is
pre-allocated so at present U-Boot wants to know the maximum
number of CPUs that may be present. Set this to at least as high
as the number of CPUs in your system (it uses about 4KB of RAM for
each CPU).
config AP_STACK_SIZE
hex
depends on SMP
default 0x1000
help
Each additional CPU started by U-Boot requires its own stack. This
@ -270,6 +279,28 @@ config TSC_FREQ_IN_MHZ
help
The running frequency in MHz of Time-Stamp Counter (TSC).
config HAVE_VGA_BIOS
bool "Add a VGA BIOS image"
help
Select this option if you have a VGA BIOS image that you would
like to add to your ROM.
config VGA_BIOS_FILE
string "VGA BIOS image filename"
depends on HAVE_VGA_BIOS
default "vga.bin"
help
The filename of the VGA BIOS image in the board directory.
config VGA_BIOS_ADDR
hex "VGA BIOS image location"
depends on HAVE_VGA_BIOS
default 0xfff90000
help
The location of VGA BIOS image in the SPI flash. For example, base
address of 0xfff90000 indicates that the image will be put at offset
0x90000 from the beginning of a 1MB flash device.
menu "System tables"
config GENERATE_PIRQ_TABLE
@ -296,6 +327,15 @@ config GENERATE_SFI_TABLE
For more information, see http://simplefirmware.org
config GENERATE_MP_TABLE
bool "Generate an MP (Multi-Processor) table"
default n
help
Generate an MP (Multi-Processor) table for this board. The MP table
provides a way for the operating system to support for symmetric
multiprocessing as well as symmetric I/O interrupt handling with
the local APIC and I/O APIC.
endmenu
config MAX_PIRQ_LINKS

View file

@ -10,7 +10,7 @@
extra-y = start.o
obj-$(CONFIG_X86_RESET_VECTOR) += resetvec.o start16.o
obj-y += interrupts.o cpu.o call64.o
obj-y += interrupts.o cpu.o cpu_x86.o call64.o
obj-$(CONFIG_INTEL_BAYTRAIL) += baytrail/
obj-$(CONFIG_SYS_COREBOOT) += coreboot/
@ -19,7 +19,7 @@ obj-$(CONFIG_NORTHBRIDGE_INTEL_SANDYBRIDGE) += ivybridge/
obj-$(CONFIG_NORTHBRIDGE_INTEL_IVYBRIDGE) += ivybridge/
obj-$(CONFIG_INTEL_QUARK) += quark/
obj-$(CONFIG_INTEL_QUEENSBAY) += queensbay/
obj-y += irq.o lapic.o
obj-y += irq.o lapic.o ioapic.o
obj-$(CONFIG_SMP) += mp_init.o
obj-y += mtrr.o
obj-$(CONFIG_PCI) += pci.o

View file

@ -7,5 +7,4 @@
obj-y += cpu.o
obj-y += early_uart.o
obj-y += fsp_configs.o
obj-y += pci.o
obj-y += valleyview.o

View file

@ -10,79 +10,11 @@
#include <cpu.h>
#include <dm.h>
#include <asm/cpu.h>
#include <asm/cpu_x86.h>
#include <asm/lapic.h>
#include <asm/mp.h>
#include <asm/msr.h>
#include <asm/turbo.h>
#ifdef CONFIG_SMP
static int enable_smis(struct udevice *cpu, void *unused)
{
return 0;
}
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++;
}
}
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;
}
static void set_max_freq(void)
{
msr_t perf_ctl;
@ -175,19 +107,38 @@ static int baytrail_get_info(struct udevice *dev, struct cpu_info *info)
return 0;
}
static int cpu_x86_baytrail_bind(struct udevice *dev)
static int baytrail_get_count(struct udevice *dev)
{
struct cpu_platdata *plat = dev_get_parent_platdata(dev);
int ecx = 0;
plat->cpu_id = fdtdec_get_int(gd->fdt_blob, dev->of_offset,
"intel,apic-id", -1);
/*
* 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++;
}
return 0;
}
static const struct cpu_ops cpu_x86_baytrail_ops = {
.get_desc = x86_cpu_get_desc,
.get_desc = cpu_x86_get_desc,
.get_info = baytrail_get_info,
.get_count = baytrail_get_count,
};
static const struct udevice_id cpu_x86_baytrail_ids[] = {
@ -199,7 +150,7 @@ 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,
.bind = cpu_x86_bind,
.probe = cpu_x86_baytrail_probe,
.ops = &cpu_x86_baytrail_ops,
};

View file

@ -1,46 +0,0 @@
/*
* Copyright (C) 2014, Bin Meng <bmeng.cn@gmail.com>
*
* SPDX-License-Identifier: GPL-2.0+
*/
#include <common.h>
#include <pci.h>
#include <asm/pci.h>
#include <asm/fsp/fsp_support.h>
DECLARE_GLOBAL_DATA_PTR;
void board_pci_setup_hose(struct pci_controller *hose)
{
hose->first_busno = 0;
hose->last_busno = 0;
/* PCI memory space */
pci_set_region(hose->regions + 0,
CONFIG_PCI_MEM_BUS,
CONFIG_PCI_MEM_PHYS,
CONFIG_PCI_MEM_SIZE,
PCI_REGION_MEM);
/* PCI IO space */
pci_set_region(hose->regions + 1,
CONFIG_PCI_IO_BUS,
CONFIG_PCI_IO_PHYS,
CONFIG_PCI_IO_SIZE,
PCI_REGION_IO);
pci_set_region(hose->regions + 2,
CONFIG_PCI_PREF_BUS,
CONFIG_PCI_PREF_PHYS,
CONFIG_PCI_PREF_SIZE,
PCI_REGION_PREFETCH);
pci_set_region(hose->regions + 3,
0,
0,
gd->ram_size < 0x80000000 ? gd->ram_size : 0x80000000,
PCI_REGION_MEM | PCI_REGION_SYS_MEMORY);
hose->region_count = 4;
}

View file

@ -10,8 +10,8 @@ CROSS_COMPILE ?= i386-linux-
PLATFORM_CPPFLAGS += -D__I386__
# DO NOT MODIFY THE FOLLOWING UNLESS YOU REALLY KNOW WHAT YOU ARE DOING!
LDPPFLAGS += -DRESET_SEG_START=0xffff0000
LDPPFLAGS += -DRESET_SEG_SIZE=0x10000
LDPPFLAGS += -DRESET_VEC_LOC=0xfffffff0
LDPPFLAGS += -DRESET_SEG_START=$(CONFIG_RESET_SEG_START)
LDPPFLAGS += -DRESET_SEG_SIZE=$(CONFIG_RESET_SEG_SIZE)
LDPPFLAGS += -DRESET_VEC_LOC=$(CONFIG_RESET_VEC_LOC)
LDPPFLAGS += -DSTART_16=$(CONFIG_SYS_X86_START16)
LDPPFLAGS += -DRESET_BASE="CONFIG_SYS_TEXT_BASE + (CONFIG_SYS_MONITOR_LEN - RESET_SEG_SIZE)"

View file

@ -11,29 +11,7 @@
#include <common.h>
#include <dm.h>
#include <errno.h>
#include <pci.h>
#include <asm/io.h>
#include <asm/pci.h>
DECLARE_GLOBAL_DATA_PTR;
static const struct dm_pci_ops pci_x86_ops = {
.read_config = pci_x86_read_config,
.write_config = pci_x86_write_config,
};
static const struct udevice_id pci_x86_ids[] = {
{ .compatible = "pci-x86" },
{ }
};
U_BOOT_DRIVER(pci_x86_drv) = {
.name = "pci_x86",
.id = UCLASS_PCI,
.of_match = pci_x86_ids,
.ops = &pci_x86_ops,
};
static const struct udevice_id generic_pch_ids[] = {
{ .compatible = "intel,pch" },

View file

@ -21,12 +21,15 @@
#include <common.h>
#include <command.h>
#include <cpu.h>
#include <dm.h>
#include <errno.h>
#include <malloc.h>
#include <asm/control_regs.h>
#include <asm/cpu.h>
#include <asm/lapic.h>
#include <asm/mp.h>
#include <asm/msr.h>
#include <asm/mtrr.h>
#include <asm/post.h>
#include <asm/processor.h>
#include <asm/processor-flags.h>
@ -164,6 +167,26 @@ void setup_gdt(gd_t *id, u64 *gdt_addr)
load_fs(X86_GDT_ENTRY_32BIT_FS);
}
#ifdef CONFIG_HAVE_FSP
/*
* Setup FSP execution environment GDT
*
* Per Intel FSP external architecture specification, before calling any FSP
* APIs, we need make sure the system is in flat 32-bit mode and both the code
* and data selectors should have full 4GB access range. Here we reuse the one
* we used in arch/x86/cpu/start16.S, and reload the segement registers.
*/
void setup_fsp_gdt(void)
{
load_gdt((const u64 *)(gdt_rom + CONFIG_RESET_SEG_START), 4);
load_ds(X86_GDT_ENTRY_32BIT_DS);
load_ss(X86_GDT_ENTRY_32BIT_DS);
load_es(X86_GDT_ENTRY_32BIT_DS);
load_fs(X86_GDT_ENTRY_32BIT_DS);
load_gs(X86_GDT_ENTRY_32BIT_DS);
}
#endif
int __weak x86_cleanup_before_linux(void)
{
#ifdef CONFIG_BOOTSTAGE_STASH
@ -330,6 +353,28 @@ int x86_cpu_init_f(void)
gd->arch.has_mtrr = has_mtrr();
}
/* Don't allow PCI region 3 to use memory in the 2-4GB memory hole */
gd->pci_ram_top = 0x80000000U;
/* Configure fixed range MTRRs for some legacy regions */
if (gd->arch.has_mtrr) {
u64 mtrr_cap;
mtrr_cap = native_read_msr(MTRR_CAP_MSR);
if (mtrr_cap & MTRR_CAP_FIX) {
/* Mark the VGA RAM area as uncacheable */
native_write_msr(MTRR_FIX_16K_A0000_MSR, 0, 0);
/* Mark the PCI ROM area as uncacheable */
native_write_msr(MTRR_FIX_4K_C0000_MSR, 0, 0);
native_write_msr(MTRR_FIX_4K_C8000_MSR, 0, 0);
native_write_msr(MTRR_FIX_4K_D0000_MSR, 0, 0);
native_write_msr(MTRR_FIX_4K_D8000_MSR, 0, 0);
/* Enable the fixed range MTRRs */
msr_setbits_64(MTRR_DEF_TYPE_MSR, MTRR_DEF_TYPE_FIX_EN);
}
}
return 0;
}
@ -520,16 +565,6 @@ char *cpu_get_name(char *name)
return ptr;
}
int x86_cpu_get_desc(struct udevice *dev, char *buf, int size)
{
if (size < CPU_MAX_NAME_LEN)
return -ENOSPC;
cpu_get_name(buf);
return 0;
}
int default_print_cpuinfo(void)
{
printf("CPU: %s, vendor %s, device %xh\n",
@ -613,8 +648,43 @@ int last_stage_init(void)
}
#endif
#ifdef CONFIG_SMP
static int enable_smis(struct udevice *cpu, void *unused)
{
return 0;
}
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 x86_mp_init(void)
{
struct mp_params mp_params;
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
__weak int x86_init_cpus(void)
{
#ifdef CONFIG_SMP
debug("Init additional CPUs\n");
x86_mp_init();
#endif
return 0;
}
@ -622,19 +692,3 @@ int cpu_init_r(void)
{
return x86_init_cpus();
}
static const struct cpu_ops cpu_x86_ops = {
.get_desc = x86_cpu_get_desc,
};
static const struct udevice_id cpu_x86_ids[] = {
{ .compatible = "cpu-x86" },
{ }
};
U_BOOT_DRIVER(cpu_x86_drv) = {
.name = "cpu_x86",
.id = UCLASS_CPU,
.of_match = cpu_x86_ids,
.ops = &cpu_x86_ops,
};

76
arch/x86/cpu/cpu_x86.c Normal file
View file

@ -0,0 +1,76 @@
/*
* Copyright (C) 2015, Bin Meng <bmeng.cn@gmail.com>
*
* SPDX-License-Identifier: GPL-2.0+
*/
#include <common.h>
#include <cpu.h>
#include <dm.h>
#include <errno.h>
#include <asm/cpu.h>
DECLARE_GLOBAL_DATA_PTR;
int cpu_x86_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;
}
int cpu_x86_get_desc(struct udevice *dev, char *buf, int size)
{
if (size < CPU_MAX_NAME_LEN)
return -ENOSPC;
cpu_get_name(buf);
return 0;
}
static int cpu_x86_get_count(struct udevice *dev)
{
int node, cpu;
int num = 0;
node = fdt_path_offset(gd->fdt_blob, "/cpus");
if (node < 0)
return -ENOENT;
for (cpu = fdt_first_subnode(gd->fdt_blob, node);
cpu >= 0;
cpu = fdt_next_subnode(gd->fdt_blob, cpu)) {
const char *device_type;
device_type = fdt_getprop(gd->fdt_blob, cpu,
"device_type", NULL);
if (!device_type)
continue;
if (strcmp(device_type, "cpu") == 0)
num++;
}
return num;
}
static const struct cpu_ops cpu_x86_ops = {
.get_desc = cpu_x86_get_desc,
.get_count = cpu_x86_get_count,
};
static const struct udevice_id cpu_x86_ids[] = {
{ .compatible = "cpu-x86" },
{ }
};
U_BOOT_DRIVER(cpu_x86_drv) = {
.name = "cpu_x86",
.id = UCLASS_CPU,
.of_match = cpu_x86_ids,
.bind = cpu_x86_bind,
.ops = &cpu_x86_ops,
};

21
arch/x86/cpu/ioapic.c Normal file
View file

@ -0,0 +1,21 @@
/*
* Copyright (C) 2015, Bin Meng <bmeng.cn@gmail.com>
*
* SPDX-License-Identifier: GPL-2.0+
*/
#include <common.h>
#include <asm/io.h>
#include <asm/ioapic.h>
u32 io_apic_read(u32 reg)
{
writel(reg, IO_APIC_INDEX);
return readl(IO_APIC_DATA);
}
void io_apic_write(u32 reg, u32 val)
{
writel(reg, IO_APIC_INDEX);
writel(val, IO_APIC_DATA);
}

View file

@ -58,17 +58,28 @@ void pirq_assign_irq(int link, u8 irq)
writeb(irq, irq_router.ibase + LINK_N2V(link, base));
}
static inline void fill_irq_info(struct irq_info **slotp, int *entries, u8 bus,
u8 device, u8 func, u8 pin, u8 pirq)
static struct irq_info *check_dup_entry(struct irq_info *slot_base,
int entry_num, int bus, int device)
{
struct irq_info *slot = *slotp;
struct irq_info *slot = slot_base;
int i;
for (i = 0; i < entry_num; i++) {
if (slot->bus == bus && slot->devfn == (device << 3))
break;
slot++;
}
return (i == entry_num) ? NULL : slot;
}
static inline void fill_irq_info(struct irq_info *slot, int bus, int device,
int pin, int pirq)
{
slot->bus = bus;
slot->devfn = (device << 3) | func;
slot->devfn = (device << 3) | 0;
slot->irq[pin - 1].link = LINK_N2V(pirq, irq_router.link_base);
slot->irq[pin - 1].bitmap = irq_router.irq_mask;
(*entries)++;
(*slotp)++;
}
__weak void cpu_irq_init(void)
@ -84,7 +95,7 @@ static int create_pirq_routing_table(void)
int len, count;
const u32 *cell;
struct irq_routing_table *rt;
struct irq_info *slot;
struct irq_info *slot, *slot_base;
int irq_entries = 0;
int i;
int ret;
@ -161,13 +172,13 @@ static int create_pirq_routing_table(void)
/* Populate the PIRQ table fields */
rt->signature = PIRQ_SIGNATURE;
rt->version = PIRQ_VERSION;
rt->rtr_bus = 0;
rt->rtr_bus = PCI_BUS(irq_router.bdf);
rt->rtr_devfn = (PCI_DEV(irq_router.bdf) << 3) |
PCI_FUNC(irq_router.bdf);
rt->rtr_vendor = PCI_VENDOR_ID_INTEL;
rt->rtr_device = PCI_DEVICE_ID_INTEL_ICH7_31;
slot = rt->slots;
slot_base = rt->slots;
/* Now fill in the irq_info entries in the PIRQ table */
for (i = 0; i < count; i++) {
@ -181,9 +192,44 @@ static int create_pirq_routing_table(void)
i, PCI_BUS(pr.bdf), PCI_DEV(pr.bdf),
PCI_FUNC(pr.bdf), 'A' + pr.pin - 1,
'A' + pr.pirq);
fill_irq_info(&slot, &irq_entries, PCI_BUS(pr.bdf),
PCI_DEV(pr.bdf), PCI_FUNC(pr.bdf),
slot = check_dup_entry(slot_base, irq_entries,
PCI_BUS(pr.bdf), PCI_DEV(pr.bdf));
if (slot) {
debug("found entry for bus %d device %d, ",
PCI_BUS(pr.bdf), PCI_DEV(pr.bdf));
if (slot->irq[pr.pin - 1].link) {
debug("skipping\n");
/*
* Sanity test on the routed PIRQ pin
*
* If they don't match, show a warning to tell
* there might be something wrong with the PIRQ
* routing information in the device tree.
*/
if (slot->irq[pr.pin - 1].link !=
LINK_N2V(pr.pirq, irq_router.link_base))
debug("WARNING: Inconsistent PIRQ routing information\n");
cell += sizeof(struct pirq_routing) /
sizeof(u32);
continue;
} else {
debug("writing INT%c\n", 'A' + pr.pin - 1);
fill_irq_info(slot, PCI_BUS(pr.bdf),
PCI_DEV(pr.bdf), pr.pin, pr.pirq);
cell += sizeof(struct pirq_routing) /
sizeof(u32);
continue;
}
}
slot = slot_base + irq_entries;
fill_irq_info(slot, PCI_BUS(pr.bdf), PCI_DEV(pr.bdf),
pr.pin, pr.pirq);
irq_entries++;
cell += sizeof(struct pirq_routing) / sizeof(u32);
}

View file

@ -95,7 +95,6 @@ config CPU_SPECIFIC_OPTIONS
select ARCH_BOOTBLOCK_X86_32
select ARCH_ROMSTAGE_X86_32
select ARCH_RAMSTAGE_X86_32
select SMP
select SSE2
select UDELAY_LAPIC
select CPU_MICROCODE_IN_CBFS

View file

@ -13,12 +13,12 @@
#include <asm/acpi.h>
#include <asm/cpu.h>
#include <asm/lapic.h>
#include <asm/lapic_def.h>
#include <asm/msr.h>
#include <asm/mtrr.h>
#include <asm/processor.h>
#include <asm/speedstep.h>
#include <asm/turbo.h>
#include <asm/arch/bd82x6x.h>
#include <asm/arch/model_206ax.h>
static void enable_vmx(void)

View file

@ -8,50 +8,153 @@
*/
#include <common.h>
#include <asm/msr.h>
#include <asm/io.h>
#include <asm/lapic.h>
#include <asm/msr.h>
#include <asm/msr-index.h>
#include <asm/post.h>
unsigned long lapic_read(unsigned long reg)
{
return readl(LAPIC_DEFAULT_BASE + reg);
}
#define xchg(ptr, v) ((__typeof__(*(ptr)))__xchg((unsigned long)(v), (ptr), \
sizeof(*(ptr))))
struct __xchg_dummy { unsigned long a[100]; };
#define __xg(x) ((struct __xchg_dummy *)(x))
/*
* Note: no "lock" prefix even on SMP. xchg always implies lock anyway.
*
* Note 2: xchg has side effect, so that attribute volatile is necessary,
* but generally the primitive is invalid, *ptr is output argument.
*/
static inline unsigned long __xchg(unsigned long x, volatile void *ptr,
int size)
{
switch (size) {
case 1:
__asm__ __volatile__("xchgb %b0,%1"
: "=q" (x)
: "m" (*__xg(ptr)), "0" (x)
: "memory");
break;
case 2:
__asm__ __volatile__("xchgw %w0,%1"
: "=r" (x)
: "m" (*__xg(ptr)), "0" (x)
: "memory");
break;
case 4:
__asm__ __volatile__("xchgl %0,%1"
: "=r" (x)
: "m" (*__xg(ptr)), "0" (x)
: "memory");
break;
}
return x;
}
void lapic_write(unsigned long reg, unsigned long v)
{
(void)xchg((volatile unsigned long *)(LAPIC_DEFAULT_BASE + reg), v);
}
void enable_lapic(void)
{
msr_t msr;
msr = msr_read(MSR_IA32_APICBASE);
msr.hi &= 0xffffff00;
msr.lo |= MSR_IA32_APICBASE_ENABLE;
msr.lo &= ~MSR_IA32_APICBASE_BASE;
msr.lo |= LAPIC_DEFAULT_BASE;
msr_write(MSR_IA32_APICBASE, msr);
}
void disable_lapic(void)
{
msr_t msr;
msr = msr_read(MSR_IA32_APICBASE);
msr.lo &= ~MSR_IA32_APICBASE_ENABLE;
msr_write(MSR_IA32_APICBASE, msr);
}
unsigned long lapicid(void)
{
return lapic_read(LAPIC_ID) >> 24;
}
static void lapic_wait_icr_idle(void)
{
do { } while (lapic_read(LAPIC_ICR) & LAPIC_ICR_BUSY);
}
int lapic_remote_read(int apicid, int reg, unsigned long *pvalue)
{
int timeout;
unsigned long status;
int result;
lapic_wait_icr_idle();
lapic_write(LAPIC_ICR2, SET_LAPIC_DEST_FIELD(apicid));
lapic_write(LAPIC_ICR, LAPIC_DM_REMRD | (reg >> 4));
timeout = 0;
do {
status = lapic_read(LAPIC_ICR) & LAPIC_ICR_RR_MASK;
} while (status == LAPIC_ICR_RR_INPROG && timeout++ < 1000);
result = -1;
if (status == LAPIC_ICR_RR_VALID) {
*pvalue = lapic_read(LAPIC_RRR);
result = 0;
}
return result;
}
void lapic_setup(void)
{
#if NEED_LAPIC == 1
#ifdef CONFIG_SMP
/* Only Pentium Pro and later have those MSR stuff */
debug("Setting up local apic: ");
/* Enable the local apic */
enable_lapic();
/*
* Set Task Priority to 'accept all'.
*/
lapic_write_around(LAPIC_TASKPRI,
lapic_read_around(LAPIC_TASKPRI) & ~LAPIC_TPRI_MASK);
/* Set Task Priority to 'accept all' */
lapic_write(LAPIC_TASKPRI,
lapic_read(LAPIC_TASKPRI) & ~LAPIC_TPRI_MASK);
/* Put the local apic in virtual wire mode */
lapic_write_around(LAPIC_SPIV, (lapic_read_around(LAPIC_SPIV) &
~(LAPIC_VECTOR_MASK)) | LAPIC_SPIV_ENABLE);
lapic_write_around(LAPIC_LVT0, (lapic_read_around(LAPIC_LVT0) &
~(LAPIC_LVT_MASKED | LAPIC_LVT_LEVEL_TRIGGER |
LAPIC_LVT_REMOTE_IRR | LAPIC_INPUT_POLARITY |
LAPIC_SEND_PENDING | LAPIC_LVT_RESERVED_1 |
LAPIC_DELIVERY_MODE_MASK)) |
(LAPIC_LVT_REMOTE_IRR | LAPIC_SEND_PENDING |
LAPIC_DELIVERY_MODE_EXTINT));
lapic_write_around(LAPIC_LVT1, (lapic_read_around(LAPIC_LVT1) &
~(LAPIC_LVT_MASKED | LAPIC_LVT_LEVEL_TRIGGER |
LAPIC_LVT_REMOTE_IRR | LAPIC_INPUT_POLARITY |
LAPIC_SEND_PENDING | LAPIC_LVT_RESERVED_1 |
LAPIC_DELIVERY_MODE_MASK)) |
(LAPIC_LVT_REMOTE_IRR | LAPIC_SEND_PENDING |
LAPIC_DELIVERY_MODE_NMI));
lapic_write(LAPIC_SPIV, (lapic_read(LAPIC_SPIV) &
~(LAPIC_VECTOR_MASK)) | LAPIC_SPIV_ENABLE);
lapic_write(LAPIC_LVT0, (lapic_read(LAPIC_LVT0) &
~(LAPIC_LVT_MASKED | LAPIC_LVT_LEVEL_TRIGGER |
LAPIC_LVT_REMOTE_IRR | LAPIC_INPUT_POLARITY |
LAPIC_SEND_PENDING | LAPIC_LVT_RESERVED_1 |
LAPIC_DELIVERY_MODE_MASK)) |
(LAPIC_LVT_REMOTE_IRR | LAPIC_SEND_PENDING |
LAPIC_DELIVERY_MODE_EXTINT));
lapic_write(LAPIC_LVT1, (lapic_read(LAPIC_LVT1) &
~(LAPIC_LVT_MASKED | LAPIC_LVT_LEVEL_TRIGGER |
LAPIC_LVT_REMOTE_IRR | LAPIC_INPUT_POLARITY |
LAPIC_SEND_PENDING | LAPIC_LVT_RESERVED_1 |
LAPIC_DELIVERY_MODE_MASK)) |
(LAPIC_LVT_REMOTE_IRR | LAPIC_SEND_PENDING |
LAPIC_DELIVERY_MODE_NMI));
debug("apic_id: 0x%02lx, ", lapicid());
#else /* !NEED_LLAPIC */
#else /* !CONFIG_SMP */
/* Only Pentium Pro and later have those MSR stuff */
debug("Disabling local apic: ");
disable_lapic();
#endif /* !NEED_LAPIC */
#endif /* CONFIG_SMP */
debug("done.\n");
post_code(POST_LAPIC);
}

View file

@ -16,12 +16,17 @@
#include <asm/interrupt.h>
#include <asm/lapic.h>
#include <asm/mp.h>
#include <asm/msr.h>
#include <asm/mtrr.h>
#include <asm/processor.h>
#include <asm/sipi.h>
#include <dm/device-internal.h>
#include <dm/uclass-internal.h>
#include <linux/linkage.h>
/* Total CPUs include BSP */
static int num_cpus;
/* This also needs to match the sipi.S assembly code for saved MSR encoding */
struct saved_msr {
uint32_t index;
@ -56,6 +61,13 @@ static inline void release_barrier(atomic_t *b)
atomic_set(b, 1);
}
static inline void stop_this_cpu(void)
{
/* Called by an AP when it is ready to halt and wait for a new task */
for (;;)
cpu_hlt();
}
/* Returns 1 if timeout waiting for APs. 0 if target APs found */
static int wait_for_aps(atomic_t *val, int target, int total_delay,
int delay_step)
@ -314,9 +326,9 @@ static int start_aps(int ap_count, atomic_t *num_aps)
}
/* Send INIT IPI to all but self */
lapic_write_around(LAPIC_ICR2, SET_LAPIC_DEST_FIELD(0));
lapic_write_around(LAPIC_ICR, LAPIC_DEST_ALLBUT | LAPIC_INT_ASSERT |
LAPIC_DM_INIT);
lapic_write(LAPIC_ICR2, SET_LAPIC_DEST_FIELD(0));
lapic_write(LAPIC_ICR, LAPIC_DEST_ALLBUT | LAPIC_INT_ASSERT |
LAPIC_DM_INIT);
debug("Waiting for 10ms after sending INIT.\n");
mdelay(10);
@ -331,9 +343,9 @@ static int start_aps(int ap_count, atomic_t *num_aps)
}
}
lapic_write_around(LAPIC_ICR2, SET_LAPIC_DEST_FIELD(0));
lapic_write_around(LAPIC_ICR, LAPIC_DEST_ALLBUT | LAPIC_INT_ASSERT |
LAPIC_DM_STARTUP | sipi_vector);
lapic_write(LAPIC_ICR2, SET_LAPIC_DEST_FIELD(0));
lapic_write(LAPIC_ICR, LAPIC_DEST_ALLBUT | LAPIC_INT_ASSERT |
LAPIC_DM_STARTUP | sipi_vector);
debug("Waiting for 1st SIPI to complete...");
if (apic_wait_timeout(10000, 50)) {
debug("timed out.\n");
@ -356,9 +368,9 @@ static int start_aps(int ap_count, atomic_t *num_aps)
}
}
lapic_write_around(LAPIC_ICR2, SET_LAPIC_DEST_FIELD(0));
lapic_write_around(LAPIC_ICR, LAPIC_DEST_ALLBUT | LAPIC_INT_ASSERT |
LAPIC_DM_STARTUP | sipi_vector);
lapic_write(LAPIC_ICR2, SET_LAPIC_DEST_FIELD(0));
lapic_write(LAPIC_ICR, LAPIC_DEST_ALLBUT | LAPIC_INT_ASSERT |
LAPIC_DM_STARTUP | sipi_vector);
debug("Waiting for 2nd SIPI to complete...");
if (apic_wait_timeout(10000, 50)) {
debug("timed out.\n");
@ -383,7 +395,7 @@ static int bsp_do_flight_plan(struct udevice *cpu, struct mp_params *mp_params)
int ret = 0;
const int timeout_us = 100000;
const int step_us = 100;
int num_aps = mp_params->num_cpus - 1;
int num_aps = num_cpus - 1;
for (i = 0; i < mp_params->num_records; i++) {
struct mp_flight_record *rec = &mp_params->flight_plan[i];
@ -415,7 +427,7 @@ static int init_bsp(struct udevice **devp)
cpu_get_name(processor_name);
debug("CPU: %s.\n", processor_name);
enable_lapic();
lapic_setup();
apic_id = lapicid();
ret = find_cpu_by_apid_id(apic_id, devp);
@ -451,7 +463,16 @@ int mp_init(struct mp_params *p)
return -1;
}
ret = check_cpu_devices(p->num_cpus);
num_cpus = cpu_get_count(cpu);
if (num_cpus < 0) {
debug("Cannot get number of CPUs: err=%d\n", num_cpus);
return num_cpus;
}
if (num_cpus < 2)
debug("Warning: Only 1 CPU is detected\n");
ret = check_cpu_devices(num_cpus);
if (ret)
debug("Warning: Device tree does not describe all CPUs. Extra ones will not be started correctly\n");
@ -471,7 +492,7 @@ int mp_init(struct mp_params *p)
wbinvd();
/* Start the APs providing number of APs and the cpus_entered field */
num_aps = p->num_cpus - 1;
num_aps = num_cpus - 1;
ret = start_aps(num_aps, ap_count);
if (ret) {
mdelay(1000);

View file

@ -38,4 +38,8 @@ config CMC_ADDR
The default base address of 0xfffb0000 indicates that the binary must
be located at offset 0xb0000 from the beginning of a 1MB flash device.
config CPU_ADDR_BITS
int
default 32
endif

View file

@ -69,17 +69,18 @@ void cpu_irq_init(void)
* Route TunnelCreek PCI device interrupt pin to PIRQ
*
* Since PCIe downstream ports received INTx are routed to PIRQ
* A/B/C/D directly and not configurable, we route internal PCI
* device's INTx to PIRQ E/F/G/H.
* A/B/C/D directly and not configurable, we have to route PCIe
* root ports' INTx to PIRQ A/B/C/D as well. For other devices
* on TunneCreek, route them to PIRQ E/F/G/H.
*/
writew(PIRQE, &rcba->d02ir);
writew(PIRQF, &rcba->d03ir);
writew(PIRQG, &rcba->d27ir);
writew(PIRQH, &rcba->d31ir);
writew(PIRQE, &rcba->d23ir);
writew(PIRQF, &rcba->d24ir);
writew(PIRQG, &rcba->d25ir);
writew(PIRQH, &rcba->d26ir);
writew(PIRQA, &rcba->d23ir);
writew(PIRQB, &rcba->d24ir);
writew(PIRQC, &rcba->d25ir);
writew(PIRQD, &rcba->d26ir);
}
int arch_misc_init(void)

View file

@ -116,12 +116,16 @@ car_init_ret:
rep stosb
#ifdef CONFIG_HAVE_FSP
test %esi, %esi
jz skip_hob
/* Store HOB list */
movl %esp, %edx
addl $GD_HOB_LIST, %edx
movl %esi, (%edx)
#endif
skip_hob:
#endif
/* Setup first parameter to setup_gdt, pointer to global_data */
movl %esp, %eax

View file

@ -71,11 +71,12 @@ idt_ptr:
*/
gdt_ptr:
.word 0x1f /* limit (31 bytes = 4 GDT entries - 1) */
.long BOOT_SEG + gdt /* base */
.long BOOT_SEG + gdt_rom /* base */
/* Some CPUs are picky about GDT alignment... */
.align 16
gdt:
.globl gdt_rom
gdt_rom:
/*
* The GDT table ...
*

View file

@ -10,6 +10,7 @@
/include/ "skeleton.dtsi"
/include/ "serial.dtsi"
/include/ "rtc.dtsi"
/ {
model = "Intel Crown Bay";
@ -23,6 +24,26 @@
silent_console = <0>;
};
cpus {
#address-cells = <1>;
#size-cells = <0>;
cpu@0 {
device_type = "cpu";
compatible = "cpu-x86";
reg = <0>;
intel,apic-id = <0>;
};
cpu@1 {
device_type = "cpu";
compatible = "cpu-x86";
reg = <1>;
intel,apic-id = <1>;
};
};
gpioa {
compatible = "intel,ich6-gpio";
u-boot,dm-pre-reloc;
@ -148,10 +169,22 @@
/* TunnelCreek PCI devices */
PCI_BDF(0, 2, 0) INTA PIRQE
PCI_BDF(0, 3, 0) INTA PIRQF
PCI_BDF(0, 23, 0) INTA PIRQE
PCI_BDF(0, 24, 0) INTA PIRQF
PCI_BDF(0, 25, 0) INTA PIRQG
PCI_BDF(0, 26, 0) INTA PIRQH
PCI_BDF(0, 23, 0) INTA PIRQA
PCI_BDF(0, 23, 0) INTB PIRQB
PCI_BDF(0, 23, 0) INTC PIRQC
PCI_BDF(0, 23, 0) INTD PIRQD
PCI_BDF(0, 24, 0) INTA PIRQB
PCI_BDF(0, 24, 0) INTB PIRQC
PCI_BDF(0, 24, 0) INTC PIRQD
PCI_BDF(0, 24, 0) INTD PIRQA
PCI_BDF(0, 25, 0) INTA PIRQC
PCI_BDF(0, 25, 0) INTB PIRQD
PCI_BDF(0, 25, 0) INTC PIRQA
PCI_BDF(0, 25, 0) INTD PIRQB
PCI_BDF(0, 26, 0) INTA PIRQD
PCI_BDF(0, 26, 0) INTB PIRQA
PCI_BDF(0, 26, 0) INTC PIRQB
PCI_BDF(0, 26, 0) INTD PIRQC
PCI_BDF(0, 27, 0) INTA PIRQG
/*
* Topcliff PCI devices
@ -159,29 +192,29 @@
* Note on the Crown Bay board, Topcliff chipset
* is connected to TunnelCreek PCIe port 0, so
* its bus number is 1 for its PCIe port and 2
* for its PCI devices per U-Boot currnet PCI
* for its PCI devices per U-Boot current PCI
* bus enumeration algorithm.
*/
PCI_BDF(1, 0, 0) INTA PIRQA
PCI_BDF(2, 0, 1) INTA PIRQA
PCI_BDF(2, 0, 2) INTA PIRQA
PCI_BDF(2, 2, 0) INTB PIRQB
PCI_BDF(2, 2, 1) INTB PIRQB
PCI_BDF(2, 2, 2) INTB PIRQB
PCI_BDF(2, 2, 3) INTB PIRQB
PCI_BDF(2, 2, 4) INTB PIRQB
PCI_BDF(2, 2, 0) INTB PIRQD
PCI_BDF(2, 2, 1) INTB PIRQD
PCI_BDF(2, 2, 2) INTB PIRQD
PCI_BDF(2, 2, 3) INTB PIRQD
PCI_BDF(2, 2, 4) INTB PIRQD
PCI_BDF(2, 4, 0) INTC PIRQC
PCI_BDF(2, 4, 1) INTC PIRQC
PCI_BDF(2, 6, 0) INTD PIRQD
PCI_BDF(2, 6, 0) INTD PIRQB
PCI_BDF(2, 8, 0) INTA PIRQA
PCI_BDF(2, 8, 1) INTA PIRQA
PCI_BDF(2, 8, 2) INTA PIRQA
PCI_BDF(2, 8, 3) INTA PIRQA
PCI_BDF(2, 10, 0) INTB PIRQB
PCI_BDF(2, 10, 1) INTB PIRQB
PCI_BDF(2, 10, 2) INTB PIRQB
PCI_BDF(2, 10, 3) INTB PIRQB
PCI_BDF(2, 10, 4) INTB PIRQB
PCI_BDF(2, 10, 0) INTB PIRQD
PCI_BDF(2, 10, 1) INTB PIRQD
PCI_BDF(2, 10, 2) INTB PIRQD
PCI_BDF(2, 10, 3) INTB PIRQD
PCI_BDF(2, 10, 4) INTB PIRQD
PCI_BDF(2, 12, 0) INTC PIRQC
PCI_BDF(2, 12, 1) INTC PIRQC
PCI_BDF(2, 12, 2) INTC PIRQC

View file

@ -111,6 +111,16 @@
};
pci {
compatible = "intel,pci-baytrail", "pci-x86";
#address-cells = <3>;
#size-cells = <2>;
u-boot,dm-pre-reloc;
ranges = <0x02000000 0x0 0xd0000000 0xd0000000 0 0x10000000
0x42000000 0x0 0xc0000000 0xc0000000 0 0x10000000
0x01000000 0x0 0x2000 0x2000 0 0xe000>;
};
spi {
#address-cells = <1>;
#size-cells = <0>;

6
arch/x86/dts/rtc.dtsi Normal file
View file

@ -0,0 +1,6 @@
/ {
rtc {
compatible = "motorola,mc146818";
reg = <0x70 2>;
};
};

View file

@ -16,7 +16,19 @@ int gma_func0_init(pci_dev_t dev, struct pci_controller *hose,
const void *blob, int node);
int bd82x6x_init(void);
struct x86_cpu_priv;
/**
* struct x86_cpu_priv - Information about a single CPU
*
* @apic_id: Advanced Programmable Interrupt Controller Identifier, which is
* just a number representing the CPU core
*
* TODO: Move this to driver model once lifecycle is understood
*/
struct x86_cpu_priv {
int apic_id;
int start_err;
};
int model_206ax_init(struct x86_cpu_priv *cpu);
#endif

View file

@ -196,20 +196,6 @@ const char *cpu_vendor_name(int vendor);
*/
char *cpu_get_name(char *name);
/**
*
* x86_cpu_get_desc() - Get a description string for an x86 CPU
*
* This uses cpu_get_name() and is suitable to use as the get_desc() method for
* the CPU uclass.
*
* @dev: Device to check (UCLASS_CPU)
* @buf: Buffer to place string
* @size: Size of string space
* @return 0 if OK, -ENOSPC if buffer is too small, other -ve on error
*/
int x86_cpu_get_desc(struct udevice *dev, char *buf, int size);
/**
* cpu_call64() - Jump to a 64-bit Linux kernel (internal function)
*

View file

@ -0,0 +1,34 @@
/*
* Copyright (C) 2015, Bin Meng <bmeng.cn@gmail.com>
*
* SPDX-License-Identifier: GPL-2.0+
*/
#ifndef _ASM_CPU_X86_H
#define _ASM_CPU_X86_H
/**
* cpu_x86_bind() - Bind an x86 CPU with the driver
*
* This updates cpu device's platform data with information from device tree,
* like the processor local apic id.
*
* @dev: Device to check (UCLASS_CPU)
* @return 0 always
*/
int cpu_x86_bind(struct udevice *dev);
/**
* cpu_x86_get_desc() - Get a description string for an x86 CPU
*
* This uses cpu_get_name() and is suitable to use as the get_desc() method for
* the CPU uclass.
*
* @dev: Device to check (UCLASS_CPU)
* @buf: Buffer to place string
* @size: Size of string space
* @return: 0 if OK, -ENOSPC if buffer is too small, other -ve on error
*/
int cpu_x86_get_desc(struct udevice *dev, char *buf, int size);
#endif /* _ASM_CPU_X86_H */

View file

@ -10,29 +10,33 @@
#define __ASM_IOAPIC_H
#define IO_APIC_ADDR 0xfec00000
#define IO_APIC_INDEX IO_APIC_ADDR
/* Direct addressed register */
#define IO_APIC_INDEX (IO_APIC_ADDR + 0x00)
#define IO_APIC_DATA (IO_APIC_ADDR + 0x10)
#define IO_APIC_INTERRUPTS 24
#define ALL (0xff << 24)
#define NONE 0
#define DISABLED (1 << 16)
#define ENABLED (0 << 16)
#define TRIGGER_EDGE (0 << 15)
#define TRIGGER_LEVEL (1 << 15)
#define POLARITY_HIGH (0 << 13)
#define POLARITY_LOW (1 << 13)
#define PHYSICAL_DEST (0 << 11)
#define LOGICAL_DEST (1 << 11)
#define ExtINT (7 << 8)
#define NMI (4 << 8)
#define SMI (2 << 8)
#define INT (1 << 8)
/* Indirect addressed register offset */
#define IO_APIC_ID 0x00
#define IO_APIC_VER 0x01
u32 io_apic_read(u32 ioapic_base, u32 reg);
void io_apic_write(u32 ioapic_base, u32 reg, u32 value);
void set_ioapic_id(u32 ioapic_base, u8 ioapic_id);
void setup_ioapic(u32 ioapic_base, u8 ioapic_id);
void clear_ioapic(u32 ioapic_base);
/**
* io_apic_read() - Read I/O APIC register
*
* This routine reads I/O APIC indirect addressed register.
*
* @reg: address of indirect addressed register
* @return: register value to read
*/
u32 io_apic_read(u32 reg);
/**
* io_apic_write() - Write I/O APIC register
*
* This routine writes I/O APIC indirect addressed register.
*
* @reg: address of indirect addressed register
* @val: register value to write
*/
void io_apic_write(u32 reg, u32 val);
#endif

View file

@ -1,5 +1,5 @@
/*
* From Coreboot file of same name
* From coreboot file of same name
*
* Copyright (C) 2014 Google, Inc
*
@ -9,171 +9,70 @@
#ifndef _ARCH_ASM_LAPIC_H
#define _ARCH_ASM_LAPIC_H
#include <asm/io.h>
#include <asm/lapic_def.h>
#include <asm/msr.h>
#include <asm/processor.h>
#define LAPIC_DEFAULT_BASE 0xfee00000
/* See if I need to initialize the local apic */
#if CONFIG_SMP || CONFIG_IOAPIC
# define NEED_LAPIC 1
#else
# define NEED_LAPIC 0
#endif
#define LAPIC_ID 0x020
#define LAPIC_LVR 0x030
static inline __attribute__((always_inline))
unsigned long lapic_read(unsigned long reg)
{
return readl(LAPIC_DEFAULT_BASE + reg);
}
#define LAPIC_TASKPRI 0x080
#define LAPIC_TPRI_MASK 0xff
static inline __attribute__((always_inline))
void lapic_write(unsigned long reg, unsigned long val)
{
writel(val, LAPIC_DEFAULT_BASE + reg);
}
#define LAPIC_RRR 0x0c0
static inline __attribute__((always_inline)) void lapic_wait_icr_idle(void)
{
do { } while (lapic_read(LAPIC_ICR) & LAPIC_ICR_BUSY);
}
#define LAPIC_SPIV 0x0f0
#define LAPIC_SPIV_ENABLE 0x100
static inline void enable_lapic(void)
{
msr_t msr;
#define LAPIC_ICR 0x300
#define LAPIC_DEST_SELF 0x40000
#define LAPIC_DEST_ALLINC 0x80000
#define LAPIC_DEST_ALLBUT 0xc0000
#define LAPIC_ICR_RR_MASK 0x30000
#define LAPIC_ICR_RR_INVALID 0x00000
#define LAPIC_ICR_RR_INPROG 0x10000
#define LAPIC_ICR_RR_VALID 0x20000
#define LAPIC_INT_LEVELTRIG 0x08000
#define LAPIC_INT_ASSERT 0x04000
#define LAPIC_ICR_BUSY 0x01000
#define LAPIC_DEST_LOGICAL 0x00800
#define LAPIC_DM_FIXED 0x00000
#define LAPIC_DM_LOWEST 0x00100
#define LAPIC_DM_SMI 0x00200
#define LAPIC_DM_REMRD 0x00300
#define LAPIC_DM_NMI 0x00400
#define LAPIC_DM_INIT 0x00500
#define LAPIC_DM_STARTUP 0x00600
#define LAPIC_DM_EXTINT 0x00700
#define LAPIC_VECTOR_MASK 0x000ff
msr = msr_read(LAPIC_BASE_MSR);
msr.hi &= 0xffffff00;
msr.lo |= LAPIC_BASE_MSR_ENABLE;
msr.lo &= ~LAPIC_BASE_MSR_ADDR_MASK;
msr.lo |= LAPIC_DEFAULT_BASE;
msr_write(LAPIC_BASE_MSR, msr);
}
#define LAPIC_ICR2 0x310
#define GET_LAPIC_DEST_FIELD(x) (((x) >> 24) & 0xff)
#define SET_LAPIC_DEST_FIELD(x) ((x) << 24)
static inline void disable_lapic(void)
{
msr_t msr;
#define LAPIC_LVT0 0x350
#define LAPIC_LVT1 0x360
#define LAPIC_LVT_MASKED (1 << 16)
#define LAPIC_LVT_LEVEL_TRIGGER (1 << 15)
#define LAPIC_LVT_REMOTE_IRR (1 << 14)
#define LAPIC_INPUT_POLARITY (1 << 13)
#define LAPIC_SEND_PENDING (1 << 12)
#define LAPIC_LVT_RESERVED_1 (1 << 11)
#define LAPIC_DELIVERY_MODE_MASK (7 << 8)
#define LAPIC_DELIVERY_MODE_FIXED (0 << 8)
#define LAPIC_DELIVERY_MODE_NMI (4 << 8)
#define LAPIC_DELIVERY_MODE_EXTINT (7 << 8)
msr = msr_read(LAPIC_BASE_MSR);
msr.lo &= ~(1 << 11);
msr_write(LAPIC_BASE_MSR, msr);
}
unsigned long lapic_read(unsigned long reg);
static inline __attribute__((always_inline)) unsigned long lapicid(void)
{
return lapic_read(LAPIC_ID) >> 24;
}
void lapic_write(unsigned long reg, unsigned long v);
#if !CONFIG_AP_IN_SIPI_WAIT
/* If we need to go back to sipi wait, we use the long non-inlined version of
* this function in lapic_cpu_init.c
*/
static inline __attribute__((always_inline)) void stop_this_cpu(void)
{
/* Called by an AP when it is ready to halt and wait for a new task */
for (;;)
cpu_hlt();
}
#else
void stop_this_cpu(void);
#endif
void enable_lapic(void);
#define xchg(ptr, v) ((__typeof__(*(ptr)))__xchg((unsigned long)(v), (ptr), \
sizeof(*(ptr))))
void disable_lapic(void);
struct __xchg_dummy { unsigned long a[100]; };
#define __xg(x) ((struct __xchg_dummy *)(x))
/*
* Note: no "lock" prefix even on SMP: xchg always implies lock anyway
* Note 2: xchg has side effect, so that attribute volatile is necessary,
* but generally the primitive is invalid, *ptr is output argument. --ANK
*/
static inline unsigned long __xchg(unsigned long x, volatile void *ptr,
int size)
{
switch (size) {
case 1:
__asm__ __volatile__("xchgb %b0,%1"
: "=q" (x)
: "m" (*__xg(ptr)), "0" (x)
: "memory");
break;
case 2:
__asm__ __volatile__("xchgw %w0,%1"
: "=r" (x)
: "m" (*__xg(ptr)), "0" (x)
: "memory");
break;
case 4:
__asm__ __volatile__("xchgl %0,%1"
: "=r" (x)
: "m" (*__xg(ptr)), "0" (x)
: "memory");
break;
}
return x;
}
static inline void lapic_write_atomic(unsigned long reg, unsigned long v)
{
(void)xchg((volatile unsigned long *)(LAPIC_DEFAULT_BASE + reg), v);
}
#ifdef X86_GOOD_APIC
# define FORCE_READ_AROUND_WRITE 0
# define lapic_read_around(x) lapic_read(x)
# define lapic_write_around(x, y) lapic_write((x), (y))
#else
# define FORCE_READ_AROUND_WRITE 1
# define lapic_read_around(x) lapic_read(x)
# define lapic_write_around(x, y) lapic_write_atomic((x), (y))
#endif
static inline int lapic_remote_read(int apicid, int reg, unsigned long *pvalue)
{
int timeout;
unsigned long status;
int result;
lapic_wait_icr_idle();
lapic_write_around(LAPIC_ICR2, SET_LAPIC_DEST_FIELD(apicid));
lapic_write_around(LAPIC_ICR, LAPIC_DM_REMRD | (reg >> 4));
timeout = 0;
do {
status = lapic_read(LAPIC_ICR) & LAPIC_ICR_RR_MASK;
} while (status == LAPIC_ICR_RR_INPROG && timeout++ < 1000);
result = -1;
if (status == LAPIC_ICR_RR_VALID) {
*pvalue = lapic_read(LAPIC_RRR);
result = 0;
}
return result;
}
unsigned long lapicid(void);
int lapic_remote_read(int apicid, int reg, unsigned long *pvalue);
void lapic_setup(void);
#if CONFIG_SMP
struct device;
int start_cpu(struct device *cpu);
#endif /* CONFIG_SMP */
int boot_cpu(void);
/**
* struct x86_cpu_priv - Information about a single CPU
*
* @apic_id: Advanced Programmable Interrupt Controller Identifier, which is
* just a number representing the CPU core
*
* TODO: Move this to driver model once lifecycle is understood
*/
struct x86_cpu_priv {
int apic_id;
int start_err;
};
#endif

View file

@ -1,101 +0,0 @@
/*
* Taken from the Coreboot file of the same name
*
* (C) Copyright 2014 Google, Inc
*
* SPDX-License-Identifier: GPL-2.0
*/
#ifndef _ASM_LAPIC_DEF_H
#define _ASM_LAPIC_DEF_H
#define LAPIC_BASE_MSR 0x1B
#define LAPIC_BASE_MSR_BOOTSTRAP_PROCESSOR (1 << 8)
#define LAPIC_BASE_MSR_ENABLE (1 << 11)
#define LAPIC_BASE_MSR_ADDR_MASK 0xFFFFF000
#define LOCAL_APIC_ADDR 0xfee00000
#define LAPIC_DEFAULT_BASE LOCAL_APIC_ADDR
#define LAPIC_ID 0x020
#define LAPIC_LVR 0x030
#define LAPIC_TASKPRI 0x80
#define LAPIC_TPRI_MASK 0xFF
#define LAPIC_ARBID 0x090
#define LAPIC_RRR 0x0C0
#define LAPIC_SVR 0x0f0
#define LAPIC_SPIV 0x0f0
#define LAPIC_SPIV_ENABLE 0x100
#define LAPIC_ESR 0x280
#define LAPIC_ESR_SEND_CS 0x00001
#define LAPIC_ESR_RECV_CS 0x00002
#define LAPIC_ESR_SEND_ACC 0x00004
#define LAPIC_ESR_RECV_ACC 0x00008
#define LAPIC_ESR_SENDILL 0x00020
#define LAPIC_ESR_RECVILL 0x00040
#define LAPIC_ESR_ILLREGA 0x00080
#define LAPIC_ICR 0x300
#define LAPIC_DEST_SELF 0x40000
#define LAPIC_DEST_ALLINC 0x80000
#define LAPIC_DEST_ALLBUT 0xC0000
#define LAPIC_ICR_RR_MASK 0x30000
#define LAPIC_ICR_RR_INVALID 0x00000
#define LAPIC_ICR_RR_INPROG 0x10000
#define LAPIC_ICR_RR_VALID 0x20000
#define LAPIC_INT_LEVELTRIG 0x08000
#define LAPIC_INT_ASSERT 0x04000
#define LAPIC_ICR_BUSY 0x01000
#define LAPIC_DEST_LOGICAL 0x00800
#define LAPIC_DM_FIXED 0x00000
#define LAPIC_DM_LOWEST 0x00100
#define LAPIC_DM_SMI 0x00200
#define LAPIC_DM_REMRD 0x00300
#define LAPIC_DM_NMI 0x00400
#define LAPIC_DM_INIT 0x00500
#define LAPIC_DM_STARTUP 0x00600
#define LAPIC_DM_EXTINT 0x00700
#define LAPIC_VECTOR_MASK 0x000FF
#define LAPIC_ICR2 0x310
#define GET_LAPIC_DEST_FIELD(x) (((x) >> 24) & 0xFF)
#define SET_LAPIC_DEST_FIELD(x) ((x) << 24)
#define LAPIC_LVTT 0x320
#define LAPIC_LVTPC 0x340
#define LAPIC_LVT0 0x350
#define LAPIC_LVT_TIMER_BASE_MASK (0x3 << 18)
#define GET_LAPIC_TIMER_BASE(x) (((x) >> 18) & 0x3)
#define SET_LAPIC_TIMER_BASE(x) (((x) << 18))
#define LAPIC_TIMER_BASE_CLKIN 0x0
#define LAPIC_TIMER_BASE_TMBASE 0x1
#define LAPIC_TIMER_BASE_DIV 0x2
#define LAPIC_LVT_TIMER_PERIODIC (1 << 17)
#define LAPIC_LVT_MASKED (1 << 16)
#define LAPIC_LVT_LEVEL_TRIGGER (1 << 15)
#define LAPIC_LVT_REMOTE_IRR (1 << 14)
#define LAPIC_INPUT_POLARITY (1 << 13)
#define LAPIC_SEND_PENDING (1 << 12)
#define LAPIC_LVT_RESERVED_1 (1 << 11)
#define LAPIC_DELIVERY_MODE_MASK (7 << 8)
#define LAPIC_DELIVERY_MODE_FIXED (0 << 8)
#define LAPIC_DELIVERY_MODE_NMI (4 << 8)
#define LAPIC_DELIVERY_MODE_EXTINT (7 << 8)
#define GET_LAPIC_DELIVERY_MODE(x) (((x) >> 8) & 0x7)
#define SET_LAPIC_DELIVERY_MODE(x, y) (((x) & ~0x700)|((y) << 8))
#define LAPIC_MODE_FIXED 0x0
#define LAPIC_MODE_NMI 0x4
#define LAPIC_MODE_EXINT 0x7
#define LAPIC_LVT1 0x360
#define LAPIC_LVTERR 0x370
#define LAPIC_TMICT 0x380
#define LAPIC_TMCCT 0x390
#define LAPIC_TDCR 0x3E0
#define LAPIC_TDR_DIV_TMBASE (1 << 2)
#define LAPIC_TDR_DIV_1 0xB
#define LAPIC_TDR_DIV_2 0x0
#define LAPIC_TDR_DIV_4 0x1
#define LAPIC_TDR_DIV_8 0x2
#define LAPIC_TDR_DIV_16 0x3
#define LAPIC_TDR_DIV_32 0x8
#define LAPIC_TDR_DIV_64 0x9
#define LAPIC_TDR_DIV_128 0xA
#endif

View file

@ -59,7 +59,6 @@ struct mp_flight_record {
* SMM support.
*/
struct mp_params {
int num_cpus; /* Total cpus include BSP */
int parallel_microcode_load;
const void *microcode_pointer;
/* Flight plan for APs and BSP */

View file

@ -0,0 +1,444 @@
/*
* Copyright (C) 2015, Bin Meng <bmeng.cn@gmail.com>
*
* Adapted from coreboot src/arch/x86/include/arch/smp/mpspec.h
*
* SPDX-License-Identifier: GPL-2.0+
*/
#ifndef __ASM_MPSPEC_H
#define __ASM_MPSPEC_H
/*
* Structure definitions for SMP machines following the
* Intel MultiProcessor Specification 1.4
*/
#define MPSPEC_V14 4
#define MPF_SIGNATURE "_MP_"
struct mp_floating_table {
char mpf_signature[4]; /* "_MP_" */
u32 mpf_physptr; /* Configuration table address */
u8 mpf_length; /* Our length (paragraphs) */
u8 mpf_spec; /* Specification version */
u8 mpf_checksum; /* Checksum (makes sum 0) */
u8 mpf_feature1; /* Predefined or Unique configuration? */
u8 mpf_feature2; /* Bit7 set for IMCR/PIC */
u8 mpf_feature3; /* Unused (0) */
u8 mpf_feature4; /* Unused (0) */
u8 mpf_feature5; /* Unused (0) */
};
#define MPC_SIGNATURE "PCMP"
struct mp_config_table {
char mpc_signature[4]; /* "PCMP" */
u16 mpc_length; /* Size of table */
u8 mpc_spec; /* Specification version */
u8 mpc_checksum; /* Checksum (makes sum 0) */
char mpc_oem[8]; /* OEM ID */
char mpc_product[12]; /* Product ID */
u32 mpc_oemptr; /* OEM table address */
u16 mpc_oemsize; /* OEM table size */
u16 mpc_entry_count; /* Number of entries in the table */
u32 mpc_lapic; /* Local APIC address */
u16 mpe_length; /* Extended table size */
u8 mpe_checksum; /* Extended table checksum */
u8 reserved;
};
/* Base MP configuration table entry types */
enum mp_base_config_entry_type {
MP_PROCESSOR,
MP_BUS,
MP_IOAPIC,
MP_INTSRC,
MP_LINTSRC
};
#define MPC_CPU_EN (1 << 0)
#define MPC_CPU_BP (1 << 1)
struct mpc_config_processor {
u8 mpc_type;
u8 mpc_apicid;
u8 mpc_apicver;
u8 mpc_cpuflag;
u32 mpc_cpusignature;
u32 mpc_cpufeature;
u32 mpc_reserved[2];
};
#define BUSTYPE_CBUS "CBUS "
#define BUSTYPE_CBUSII "CBUSII"
#define BUSTYPE_EISA "EISA "
#define BUSTYPE_FUTURE "FUTURE"
#define BUSTYPE_INTERN "INTERN"
#define BUSTYPE_ISA "ISA "
#define BUSTYPE_MBI "MBI "
#define BUSTYPE_MBII "MBII "
#define BUSTYPE_MCA "MCA "
#define BUSTYPE_MPI "MPI "
#define BUSTYPE_MPSA "MPSA "
#define BUSTYPE_NUBUS "NUBUS "
#define BUSTYPE_PCI "PCI "
#define BUSTYPE_PCMCIA "PCMCIA"
#define BUSTYPE_TC "TC "
#define BUSTYPE_VL "VL "
#define BUSTYPE_VME "VME "
#define BUSTYPE_XPRESS "XPRESS"
struct mpc_config_bus {
u8 mpc_type;
u8 mpc_busid;
u8 mpc_bustype[6];
};
#define MPC_APIC_USABLE (1 << 0)
struct mpc_config_ioapic {
u8 mpc_type;
u8 mpc_apicid;
u8 mpc_apicver;
u8 mpc_flags;
u32 mpc_apicaddr;
};
enum mp_irq_source_types {
MP_INT,
MP_NMI,
MP_SMI,
MP_EXTINT
};
#define MP_IRQ_POLARITY_DEFAULT 0x0
#define MP_IRQ_POLARITY_HIGH 0x1
#define MP_IRQ_POLARITY_LOW 0x3
#define MP_IRQ_POLARITY_MASK 0x3
#define MP_IRQ_TRIGGER_DEFAULT 0x0
#define MP_IRQ_TRIGGER_EDGE 0x4
#define MP_IRQ_TRIGGER_LEVEL 0xc
#define MP_IRQ_TRIGGER_MASK 0xc
#define MP_APIC_ALL 0xff
struct mpc_config_intsrc {
u8 mpc_type;
u8 mpc_irqtype;
u16 mpc_irqflag;
u8 mpc_srcbus;
u8 mpc_srcbusirq;
u8 mpc_dstapic;
u8 mpc_dstirq;
};
struct mpc_config_lintsrc {
u8 mpc_type;
u8 mpc_irqtype;
u16 mpc_irqflag;
u8 mpc_srcbusid;
u8 mpc_srcbusirq;
u8 mpc_destapic;
u8 mpc_destlint;
};
/* Extended MP configuration table entry types */
enum mp_ext_config_entry_type {
MPE_SYSTEM_ADDRESS_SPACE = 128,
MPE_BUS_HIERARCHY,
MPE_COMPAT_ADDRESS_SPACE
};
struct mp_ext_config {
u8 mpe_type;
u8 mpe_length;
};
#define ADDRESS_TYPE_IO 0
#define ADDRESS_TYPE_MEM 1
#define ADDRESS_TYPE_PREFETCH 2
struct mp_ext_system_address_space {
u8 mpe_type;
u8 mpe_length;
u8 mpe_busid;
u8 mpe_addr_type;
u32 mpe_addr_base_low;
u32 mpe_addr_base_high;
u32 mpe_addr_length_low;
u32 mpe_addr_length_high;
};
#define BUS_SUBTRACTIVE_DECODE (1 << 0)
struct mp_ext_bus_hierarchy {
u8 mpe_type;
u8 mpe_length;
u8 mpe_busid;
u8 mpe_bus_info;
u8 mpe_parent_busid;
u8 reserved[3];
};
#define ADDRESS_RANGE_ADD 0
#define ADDRESS_RANGE_SUBTRACT 1
/*
* X100 - X3FF
* X500 - X7FF
* X900 - XBFF
* XD00 - XFFF
*/
#define RANGE_LIST_IO_ISA 0
/*
* X3B0 - X3BB
* X3C0 - X3DF
* X7B0 - X7BB
* X7C0 - X7DF
* XBB0 - XBBB
* XBC0 - XBDF
* XFB0 - XFBB
* XFC0 - XCDF
*/
#define RANGE_LIST_IO_VGA 1
struct mp_ext_compat_address_space {
u8 mpe_type;
u8 mpe_length;
u8 mpe_busid;
u8 mpe_addr_modifier;
u32 mpe_range_list;
};
/**
* mp_next_mpc_entry() - Compute MP configuration table end to be used as
* next base table entry start address
*
* This computes the end address of current MP configuration table, without
* counting any extended configuration table entry.
*
* @mc: configuration table header address
* @return: configuration table end address
*/
static inline u32 mp_next_mpc_entry(struct mp_config_table *mc)
{
return (u32)mc + mc->mpc_length;
}
/**
* mp_add_mpc_entry() - Add a base MP configuration table entry
*
* This adds the base MP configuration table entry size with
* added base table entry length and increases entry count by 1.
*
* @mc: configuration table header address
* @length: length of the added table entry
*/
static inline void mp_add_mpc_entry(struct mp_config_table *mc, uint length)
{
mc->mpc_length += length;
mc->mpc_entry_count++;
}
/**
* mp_next_mpe_entry() - Compute MP configuration table end to be used as
* next extended table entry start address
*
* This computes the end address of current MP configuration table,
* including any extended configuration table entry.
*
* @mc: configuration table header address
* @return: configuration table end address
*/
static inline u32 mp_next_mpe_entry(struct mp_config_table *mc)
{
return (u32)mc + mc->mpc_length + mc->mpe_length;
}
/**
* mp_add_mpe_entry() - Add an extended MP configuration table entry
*
* This adds the extended MP configuration table entry size with
* added extended table entry length.
*
* @mc: configuration table header address
* @mpe: extended table entry base address
*/
static inline void mp_add_mpe_entry(struct mp_config_table *mc,
struct mp_ext_config *mpe)
{
mc->mpe_length += mpe->mpe_length;
}
/**
* mp_write_floating_table() - Write the MP floating table
*
* This writes the MP floating table, and points MP configuration table
* to its end address so that MP configuration table follows immediately
* after the floating table.
*
* @mf: MP floating table base address
* @return: MP configuration table header address
*/
struct mp_config_table *mp_write_floating_table(struct mp_floating_table *mf);
/**
* mp_config_table_init() - Initialize the MP configuration table header
*
* This populates the MP configuration table header with valid bits.
*
* @mc: MP configuration table header address
*/
void mp_config_table_init(struct mp_config_table *mc);
/**
* mp_write_processor() - Write a processor entry
*
* This writes a processor entry to the configuration table.
*
* @mc: MP configuration table header address
*/
void mp_write_processor(struct mp_config_table *mc);
/**
* mp_write_bus() - Write a bus entry
*
* This writes a bus entry to the configuration table.
*
* @mc: MP configuration table header address
* @id: bus id
* @bustype: bus type name
*/
void mp_write_bus(struct mp_config_table *mc, int id, const char *bustype);
/**
* mp_write_ioapic() - Write an I/O APIC entry
*
* This writes an I/O APIC entry to the configuration table.
*
* @mc: MP configuration table header address
* @id: I/O APIC id
* @ver: I/O APIC version
* @apicaddr: I/O APIC address
*/
void mp_write_ioapic(struct mp_config_table *mc, int id, int ver, u32 apicaddr);
/**
* mp_write_intsrc() - Write an I/O interrupt assignment entry
*
* This writes an I/O interrupt assignment entry to the configuration table.
*
* @mc: MP configuration table header address
* @irqtype: IRQ type (INT/NMI/SMI/ExtINT)
* @irqflag: IRQ flag (level/trigger)
* @srcbus: source bus id where the interrupt comes from
* @srcbusirq: IRQ number mapped on the source bus
* @dstapic: destination I/O APIC id where the interrupt goes to
* @dstirq: destination I/O APIC pin where the interrupt goes to
*/
void mp_write_intsrc(struct mp_config_table *mc, int irqtype, int irqflag,
int srcbus, int srcbusirq, int dstapic, int dstirq);
/**
* mp_write_pci_intsrc() - Write a PCI interrupt assignment entry
*
* This writes a PCI interrupt assignment entry to the configuration table.
*
* @mc: MP configuration table header address
* @irqtype: IRQ type (INT/NMI/SMI/ExtINT)
* @srcbus: PCI bus number where the interrupt comes from
* @dev: device number on the PCI bus
* @pin: PCI interrupt pin (INT A/B/C/D)
* @dstapic: destination I/O APIC id where the interrupt goes to
* @dstirq: destination I/O APIC pin where the interrupt goes to
*/
void mp_write_pci_intsrc(struct mp_config_table *mc, int irqtype,
int srcbus, int dev, int pin, int dstapic, int dstirq);
/**
* mp_write_lintsrc() - Write a local interrupt assignment entry
*
* This writes a local interrupt assignment entry to the configuration table.
*
* @mc: MP configuration table header address
* @irqtype: IRQ type (INT/NMI/SMI/ExtINT)
* @irqflag: IRQ flag (level/trigger)
* @srcbus: PCI bus number where the interrupt comes from
* @srcbusirq: IRQ number mapped on the source bus
* @dstapic: destination local APIC id where the interrupt goes to
* @destlint: destination local APIC pin where the interrupt goes to
*/
void mp_write_lintsrc(struct mp_config_table *mc, int irqtype, int irqflag,
int srcbus, int srcbusirq, int destapic, int destlint);
/**
* mp_write_address_space() - Write a system address space entry
*
* This writes a system address space entry to the configuration table.
*
* @mc: MP configuration table header address
* @busid: bus id for the bus where system address space is mapped
* @addr_type: system address type
* @addr_base_low: starting address low
* @addr_base_high: starting address high
* @addr_length_low: address length low
* @addr_length_high: address length high
*/
void mp_write_address_space(struct mp_config_table *mc,
int busid, int addr_type,
u32 addr_base_low, u32 addr_base_high,
u32 addr_length_low, u32 addr_length_high);
/**
* mp_write_bus_hierarchy() - Write a bus hierarchy descriptor entry
*
* This writes a bus hierarchy descriptor entry to the configuration table.
*
* @mc: MP configuration table header address
* @busid: bus id
* @bus_info: bit0 indicates if the bus is a subtractive decode bus
* @parent_busid: parent bus id
*/
void mp_write_bus_hierarchy(struct mp_config_table *mc,
int busid, int bus_info, int parent_busid);
/**
* mp_write_compat_address_space() - Write a compat bus address space entry
*
* This writes a compatibility bus address space modifier entry to the
* configuration table.
*
* @mc: MP configuration table header address
* @busid: bus id
* @addr_modifier: add or subtract to predefined address range list
* @range_list: list of predefined address space ranges
*/
void mp_write_compat_address_space(struct mp_config_table *mc, int busid,
int addr_modifier, u32 range_list);
/**
* mptable_finalize() - Finalize the MP table
*
* This finalizes the MP table by calculating required checksums.
*
* @mc: MP configuration table header address
* @return: MP table end address
*/
u32 mptable_finalize(struct mp_config_table *mc);
/**
* write_mp_table() - Write MP table
*
* This writes MP table at a given address.
*
* @addr: start address to write MP table
* @return: end address of MP table
*/
u32 write_mp_table(u32 addr);
#endif /* __ASM_MPSPEC_H */

View file

@ -21,6 +21,11 @@
#define MTRR_CAP_MSR 0x0fe
#define MTRR_DEF_TYPE_MSR 0x2ff
#define MTRR_CAP_SMRR (1 << 11)
#define MTRR_CAP_WC (1 << 10)
#define MTRR_CAP_FIX (1 << 8)
#define MTRR_CAP_VCNT_MASK 0xff
#define MTRR_DEF_TYPE_EN (1 << 11)
#define MTRR_DEF_TYPE_FIX_EN (1 << 10)
@ -38,17 +43,17 @@
#define RANGES_PER_FIXED_MTRR 8
#define NUM_FIXED_RANGES (NUM_FIXED_MTRRS * RANGES_PER_FIXED_MTRR)
#define MTRR_FIX_64K_00000_MSR 0x250
#define MTRR_FIX_16K_80000_MSR 0x258
#define MTRR_FIX_16K_A0000_MSR 0x259
#define MTRR_FIX_4K_C0000_MSR 0x268
#define MTRR_FIX_4K_C8000_MSR 0x269
#define MTRR_FIX_4K_D0000_MSR 0x26a
#define MTRR_FIX_4K_D8000_MSR 0x26b
#define MTRR_FIX_4K_E0000_MSR 0x26c
#define MTRR_FIX_4K_E8000_MSR 0x26d
#define MTRR_FIX_4K_F0000_MSR 0x26e
#define MTRR_FIX_4K_F8000_MSR 0x26f
#define MTRR_FIX_64K_00000_MSR 0x250
#define MTRR_FIX_16K_80000_MSR 0x258
#define MTRR_FIX_16K_A0000_MSR 0x259
#define MTRR_FIX_4K_C0000_MSR 0x268
#define MTRR_FIX_4K_C8000_MSR 0x269
#define MTRR_FIX_4K_D0000_MSR 0x26a
#define MTRR_FIX_4K_D8000_MSR 0x26b
#define MTRR_FIX_4K_E0000_MSR 0x26c
#define MTRR_FIX_4K_E8000_MSR 0x26d
#define MTRR_FIX_4K_F0000_MSR 0x26e
#define MTRR_FIX_4K_F8000_MSR 0x26f
#if !defined(__ASSEMBLER__)

View file

@ -27,6 +27,20 @@
*/
u8 table_compute_checksum(void *v, int len);
/**
* table_fill_string() - Fill a string with pad in the configuration table
*
* This fills a string in the configuration table. It copies number of bytes
* from the source string, and if source string length is shorter than the
* required size to copy, pad the table string with the given pad character.
*
* @dest: where to fill a string
* @src: where to copy from
* @n: number of bytes to copy
* @pad: character to pad the remaining bytes
*/
void table_fill_string(char *dest, const char *src, size_t n, char pad);
/**
* write_tables() - Write x86 configuration tables
*

View file

@ -8,12 +8,19 @@
#ifndef _U_BOOT_I386_H_
#define _U_BOOT_I386_H_ 1
extern char gdt_rom[];
/* cpu/.../cpu.c */
int arch_cpu_init(void);
int x86_cpu_init_f(void);
int cpu_init_f(void);
void init_gd(gd_t *id, u64 *gdt_addr);
void setup_gdt(gd_t *id, u64 *gdt_addr);
/*
* Setup FSP execution environment GDT to use the one we used in
* arch/x86/cpu/start16.S and reload the segment registers.
*/
void setup_fsp_gdt(void);
int init_cache(void);
int cleanup_before_linux(void);
@ -49,6 +56,9 @@ u32 isa_map_rom(u32 bus_addr, int size);
/* arch/x86/lib/... */
int video_bios_init(void);
/* arch/x86/lib/fsp/... */
int x86_fsp_init(void);
void board_init_f_r_trampoline(ulong) __attribute__ ((noreturn));
void board_init_f_r(void) __attribute__ ((noreturn));

View file

@ -38,5 +38,6 @@ struct boot_params *load_zimage(char *image, unsigned long kernel_size,
ulong *load_addressp);
int setup_zimage(struct boot_params *setup_base, char *cmd_line, int auto_boot,
unsigned long initrd_addr, unsigned long initrd_size);
void setup_video(struct screen_info *screen_info);
#endif

View file

@ -15,6 +15,7 @@ obj-y += gcc.o
obj-y += init_helpers.o
obj-y += interrupts.o
obj-y += lpc-uclass.o
obj-y += mpspec.o
obj-y += cmd_mtrr.o
obj-$(CONFIG_SYS_PCAT_INTERRUPTS) += pcat_interrupts.o
obj-$(CONFIG_SYS_PCAT_TIMER) += pcat_timer.o

View file

@ -246,6 +246,9 @@ __interrupt_handler_16bit = PTR_TO_REAL_MODE(.)
push %fs
push %gs
/* Save real mode SS */
movw %ss, %cs:__realmode_ss
/* Clear DF to not break ABI assumptions */
cld
@ -258,12 +261,29 @@ __interrupt_handler_16bit = PTR_TO_REAL_MODE(.)
enter_protected_mode
/*
* Now we are in protected mode. We need compute the right ESP based
* on saved real mode SS otherwise interrupt_handler() won't get
* correct parameters from the stack.
*/
movzwl %cs:__realmode_ss, %ecx
shll $4, %ecx
addl %ecx, %esp
/* Call the C interrupt handler */
movl $interrupt_handler, %eax
call *%eax
/* Restore real mode ESP based on saved SS */
movzwl %cs:__realmode_ss, %ecx
shll $4, %ecx
subl %ecx, %esp
enter_real_mode
/* Restore real mode SS */
movw %cs:__realmode_ss, %ss
/*
* Restore all registers, including those manipulated by the C
* handler
@ -276,6 +296,9 @@ __interrupt_handler_16bit = PTR_TO_REAL_MODE(.)
popal
iret
__realmode_ss = PTR_TO_REAL_MODE(.)
.word 0
.globl asm_realmode_code_size
asm_realmode_code_size:
.long . - asm_realmode_code

View file

@ -161,15 +161,7 @@ int int1a_handler(void)
bus = M.x86.R_EBX >> 8;
reg = M.x86.R_EDI;
dev = PCI_BDF(bus, devfn >> 3, devfn & 7);
if (!dev) {
debug("0x%x: BAD DEVICE bus %d devfn 0x%x\n", func,
bus, devfn);
/* Or are we supposed to return PCIBIOS_NODEV? */
M.x86.R_EAX &= 0xffff00ff; /* Clear AH */
M.x86.R_EAX |= PCIBIOS_BADREG;
retval = 0;
return retval;
}
switch (func) {
case 0xb108: /* Read Config Byte */
byte = x86_pci_read_config8(dev, reg);

View file

@ -37,7 +37,8 @@ static int do_mtrr_list(void)
valid = mask & MTRR_PHYS_MASK_VALID;
type = mtrr_type_name[base & MTRR_BASE_TYPE_MASK];
printf("%d %-5s %-12s %016llx %016llx %016llx\n", i,
valid ? "Y" : "N", type, base, mask, size);
valid ? "Y" : "N", type, base & ~MTRR_BASE_TYPE_MASK,
mask & ~MTRR_PHYS_MASK_VALID, size);
}
return 0;

View file

@ -56,28 +56,10 @@ temp_ram_init_ret:
/* stack grows down from top of CAR */
movl %edx, %esp
subl $4, %esp
/*
* TODO:
*
* According to FSP architecture spec, the fsp_init() will not return
* to its caller, instead it requires the bootloader to provide a
* so-called continuation function to pass into the FSP as a parameter
* of fsp_init, and fsp_init() will call that continuation function
* directly.
*
* The call to fsp_init() may need to be moved out of the car_init()
* to cpu_init_f() with the help of some inline assembly codes.
* Note there is another issue that fsp_init() will setup another stack
* using the fsp_init parameter stack_top after DRAM is initialized,
* which means any data on the previous stack (on the CAR) gets lost
* (ie: U-Boot global_data). FSP is supposed to support such scenario,
* however it does not work. This should be revisited in the future.
*/
movl $CONFIG_FSP_TEMP_RAM_ADDR, %eax
xorl %edx, %edx
xorl %ecx, %ecx
call fsp_init
xor %esi, %esi
jmp car_init_done
.global fsp_init_done
fsp_init_done:
@ -86,6 +68,8 @@ fsp_init_done:
* Save eax to esi temporarily.
*/
movl %eax, %esi
car_init_done:
/*
* Re-initialize the ebp (BIST) to zero, as we already reach here
* which means we passed BIST testing before.

View file

@ -46,3 +46,11 @@ void board_final_cleanup(void)
return;
}
int x86_fsp_init(void)
{
if (!gd->arch.hob_list)
fsp_init(CONFIG_FSP_TEMP_RAM_ADDR, BOOT_FULL_CONFIG, NULL);
return 0;
}

View file

@ -173,6 +173,9 @@ void fsp_init(u32 stack_top, u32 boot_mode, void *nvs_buf)
post_code(POST_PRE_MRC);
/* Load GDT for FSP */
setup_fsp_gdt();
/*
* Use ASM code to ensure the register value in EAX & ECX
* will be passed into BlContinuationFunc

382
arch/x86/lib/mpspec.c Normal file
View file

@ -0,0 +1,382 @@
/*
* Copyright (C) 2015, Bin Meng <bmeng.cn@gmail.com>
*
* Adapted from coreboot src/arch/x86/boot/mpspec.c
*
* SPDX-License-Identifier: GPL-2.0+
*/
#include <common.h>
#include <cpu.h>
#include <dm.h>
#include <errno.h>
#include <fdtdec.h>
#include <asm/cpu.h>
#include <asm/irq.h>
#include <asm/ioapic.h>
#include <asm/lapic.h>
#include <asm/mpspec.h>
#include <asm/tables.h>
#include <dm/uclass-internal.h>
DECLARE_GLOBAL_DATA_PTR;
struct mp_config_table *mp_write_floating_table(struct mp_floating_table *mf)
{
u32 mc;
memcpy(mf->mpf_signature, MPF_SIGNATURE, 4);
mf->mpf_physptr = (u32)mf + sizeof(struct mp_floating_table);
mf->mpf_length = 1;
mf->mpf_spec = MPSPEC_V14;
mf->mpf_checksum = 0;
/* We don't use the default configuration table */
mf->mpf_feature1 = 0;
/* Indicate that virtual wire mode is always implemented */
mf->mpf_feature2 = 0;
mf->mpf_feature3 = 0;
mf->mpf_feature4 = 0;
mf->mpf_feature5 = 0;
mf->mpf_checksum = table_compute_checksum(mf, mf->mpf_length * 16);
mc = (u32)mf + sizeof(struct mp_floating_table);
return (struct mp_config_table *)mc;
}
void mp_config_table_init(struct mp_config_table *mc)
{
memcpy(mc->mpc_signature, MPC_SIGNATURE, 4);
mc->mpc_length = sizeof(struct mp_config_table);
mc->mpc_spec = MPSPEC_V14;
mc->mpc_checksum = 0;
mc->mpc_oemptr = 0;
mc->mpc_oemsize = 0;
mc->mpc_entry_count = 0;
mc->mpc_lapic = LAPIC_DEFAULT_BASE;
mc->mpe_length = 0;
mc->mpe_checksum = 0;
mc->reserved = 0;
/* The oem/product id fields are exactly 8/12 bytes long */
table_fill_string(mc->mpc_oem, CONFIG_SYS_VENDOR, 8, ' ');
table_fill_string(mc->mpc_product, CONFIG_SYS_BOARD, 12, ' ');
}
void mp_write_processor(struct mp_config_table *mc)
{
struct mpc_config_processor *mpc;
struct udevice *dev;
u8 boot_apicid, apicver;
u32 cpusignature, cpufeature;
struct cpuid_result result;
boot_apicid = lapicid();
apicver = lapic_read(LAPIC_LVR) & 0xff;
result = cpuid(1);
cpusignature = result.eax;
cpufeature = result.edx;
for (uclass_find_first_device(UCLASS_CPU, &dev);
dev;
uclass_find_next_device(&dev)) {
struct cpu_platdata *plat = dev_get_parent_platdata(dev);
u8 cpuflag = MPC_CPU_EN;
if (!device_active(dev))
continue;
mpc = (struct mpc_config_processor *)mp_next_mpc_entry(mc);
mpc->mpc_type = MP_PROCESSOR;
mpc->mpc_apicid = plat->cpu_id;
mpc->mpc_apicver = apicver;
if (boot_apicid == plat->cpu_id)
cpuflag |= MPC_CPU_BP;
mpc->mpc_cpuflag = cpuflag;
mpc->mpc_cpusignature = cpusignature;
mpc->mpc_cpufeature = cpufeature;
mpc->mpc_reserved[0] = 0;
mpc->mpc_reserved[1] = 0;
mp_add_mpc_entry(mc, sizeof(*mpc));
}
}
void mp_write_bus(struct mp_config_table *mc, int id, const char *bustype)
{
struct mpc_config_bus *mpc;
mpc = (struct mpc_config_bus *)mp_next_mpc_entry(mc);
mpc->mpc_type = MP_BUS;
mpc->mpc_busid = id;
memcpy(mpc->mpc_bustype, bustype, 6);
mp_add_mpc_entry(mc, sizeof(*mpc));
}
void mp_write_ioapic(struct mp_config_table *mc, int id, int ver, u32 apicaddr)
{
struct mpc_config_ioapic *mpc;
mpc = (struct mpc_config_ioapic *)mp_next_mpc_entry(mc);
mpc->mpc_type = MP_IOAPIC;
mpc->mpc_apicid = id;
mpc->mpc_apicver = ver;
mpc->mpc_flags = MPC_APIC_USABLE;
mpc->mpc_apicaddr = apicaddr;
mp_add_mpc_entry(mc, sizeof(*mpc));
}
void mp_write_intsrc(struct mp_config_table *mc, int irqtype, int irqflag,
int srcbus, int srcbusirq, int dstapic, int dstirq)
{
struct mpc_config_intsrc *mpc;
mpc = (struct mpc_config_intsrc *)mp_next_mpc_entry(mc);
mpc->mpc_type = MP_INTSRC;
mpc->mpc_irqtype = irqtype;
mpc->mpc_irqflag = irqflag;
mpc->mpc_srcbus = srcbus;
mpc->mpc_srcbusirq = srcbusirq;
mpc->mpc_dstapic = dstapic;
mpc->mpc_dstirq = dstirq;
mp_add_mpc_entry(mc, sizeof(*mpc));
}
void mp_write_pci_intsrc(struct mp_config_table *mc, int irqtype,
int srcbus, int dev, int pin, int dstapic, int dstirq)
{
u8 srcbusirq = (dev << 2) | (pin - 1);
mp_write_intsrc(mc, irqtype, MP_IRQ_TRIGGER_LEVEL | MP_IRQ_POLARITY_LOW,
srcbus, srcbusirq, dstapic, dstirq);
}
void mp_write_lintsrc(struct mp_config_table *mc, int irqtype, int irqflag,
int srcbus, int srcbusirq, int destapic, int destlint)
{
struct mpc_config_lintsrc *mpc;
mpc = (struct mpc_config_lintsrc *)mp_next_mpc_entry(mc);
mpc->mpc_type = MP_LINTSRC;
mpc->mpc_irqtype = irqtype;
mpc->mpc_irqflag = irqflag;
mpc->mpc_srcbusid = srcbus;
mpc->mpc_srcbusirq = srcbusirq;
mpc->mpc_destapic = destapic;
mpc->mpc_destlint = destlint;
mp_add_mpc_entry(mc, sizeof(*mpc));
}
void mp_write_address_space(struct mp_config_table *mc,
int busid, int addr_type,
u32 addr_base_low, u32 addr_base_high,
u32 addr_length_low, u32 addr_length_high)
{
struct mp_ext_system_address_space *mpe;
mpe = (struct mp_ext_system_address_space *)mp_next_mpe_entry(mc);
mpe->mpe_type = MPE_SYSTEM_ADDRESS_SPACE;
mpe->mpe_length = sizeof(*mpe);
mpe->mpe_busid = busid;
mpe->mpe_addr_type = addr_type;
mpe->mpe_addr_base_low = addr_base_low;
mpe->mpe_addr_base_high = addr_base_high;
mpe->mpe_addr_length_low = addr_length_low;
mpe->mpe_addr_length_high = addr_length_high;
mp_add_mpe_entry(mc, (struct mp_ext_config *)mpe);
}
void mp_write_bus_hierarchy(struct mp_config_table *mc,
int busid, int bus_info, int parent_busid)
{
struct mp_ext_bus_hierarchy *mpe;
mpe = (struct mp_ext_bus_hierarchy *)mp_next_mpe_entry(mc);
mpe->mpe_type = MPE_BUS_HIERARCHY;
mpe->mpe_length = sizeof(*mpe);
mpe->mpe_busid = busid;
mpe->mpe_bus_info = bus_info;
mpe->mpe_parent_busid = parent_busid;
mpe->reserved[0] = 0;
mpe->reserved[1] = 0;
mpe->reserved[2] = 0;
mp_add_mpe_entry(mc, (struct mp_ext_config *)mpe);
}
void mp_write_compat_address_space(struct mp_config_table *mc, int busid,
int addr_modifier, u32 range_list)
{
struct mp_ext_compat_address_space *mpe;
mpe = (struct mp_ext_compat_address_space *)mp_next_mpe_entry(mc);
mpe->mpe_type = MPE_COMPAT_ADDRESS_SPACE;
mpe->mpe_length = sizeof(*mpe);
mpe->mpe_busid = busid;
mpe->mpe_addr_modifier = addr_modifier;
mpe->mpe_range_list = range_list;
mp_add_mpe_entry(mc, (struct mp_ext_config *)mpe);
}
u32 mptable_finalize(struct mp_config_table *mc)
{
u32 end;
mc->mpe_checksum = table_compute_checksum((void *)mp_next_mpc_entry(mc),
mc->mpe_length);
mc->mpc_checksum = table_compute_checksum(mc, mc->mpc_length);
end = mp_next_mpe_entry(mc);
debug("Write the MP table at: %x - %x\n", (u32)mc, end);
return end;
}
static void mptable_add_isa_interrupts(struct mp_config_table *mc, int bus_isa,
int apicid, int external_int2)
{
int i;
mp_write_intsrc(mc, external_int2 ? MP_INT : MP_EXTINT,
MP_IRQ_TRIGGER_EDGE | MP_IRQ_POLARITY_HIGH,
bus_isa, 0, apicid, 0);
mp_write_intsrc(mc, MP_INT, MP_IRQ_TRIGGER_EDGE | MP_IRQ_POLARITY_HIGH,
bus_isa, 1, apicid, 1);
mp_write_intsrc(mc, external_int2 ? MP_EXTINT : MP_INT,
MP_IRQ_TRIGGER_EDGE | MP_IRQ_POLARITY_HIGH,
bus_isa, 0, apicid, 2);
for (i = 3; i < 16; i++)
mp_write_intsrc(mc, MP_INT,
MP_IRQ_TRIGGER_EDGE | MP_IRQ_POLARITY_HIGH,
bus_isa, i, apicid, i);
}
/*
* Check duplicated I/O interrupt assignment table entry, to make sure
* there is only one entry with the given bus, device and interrupt pin.
*/
static bool check_dup_entry(struct mpc_config_intsrc *intsrc_base,
int entry_num, int bus, int device, int pin)
{
struct mpc_config_intsrc *intsrc = intsrc_base;
int i;
for (i = 0; i < entry_num; i++) {
if (intsrc->mpc_srcbus == bus &&
intsrc->mpc_srcbusirq == ((device << 2) | (pin - 1)))
break;
intsrc++;
}
return (i == entry_num) ? false : true;
}
static int mptable_add_intsrc(struct mp_config_table *mc,
int bus_isa, int apicid)
{
struct mpc_config_intsrc *intsrc_base;
int intsrc_entries = 0;
const void *blob = gd->fdt_blob;
int node;
int len, count;
const u32 *cell;
int i;
/* Legacy Interrupts */
debug("Writing ISA IRQs\n");
mptable_add_isa_interrupts(mc, bus_isa, apicid, 0);
/* Get I/O interrupt information from device tree */
node = fdtdec_next_compatible(blob, 0, COMPAT_INTEL_IRQ_ROUTER);
if (node < 0) {
debug("%s: Cannot find irq router node\n", __func__);
return -ENOENT;
}
cell = fdt_getprop(blob, node, "intel,pirq-routing", &len);
if (!cell)
return -ENOENT;
if ((len % sizeof(struct pirq_routing)) == 0)
count = len / sizeof(struct pirq_routing);
else
return -EINVAL;
intsrc_base = (struct mpc_config_intsrc *)mp_next_mpc_entry(mc);
for (i = 0; i < count; i++) {
struct pirq_routing pr;
pr.bdf = fdt_addr_to_cpu(cell[0]);
pr.pin = fdt_addr_to_cpu(cell[1]);
pr.pirq = fdt_addr_to_cpu(cell[2]);
if (check_dup_entry(intsrc_base, intsrc_entries,
PCI_BUS(pr.bdf), PCI_DEV(pr.bdf), pr.pin)) {
debug("found entry for bus %d device %d INT%c, skipping\n",
PCI_BUS(pr.bdf), PCI_DEV(pr.bdf),
'A' + pr.pin - 1);
cell += sizeof(struct pirq_routing) / sizeof(u32);
continue;
}
/* PIRQ[A-H] are always connected to I/O APIC INTPIN#16-23 */
mp_write_pci_intsrc(mc, MP_INT, PCI_BUS(pr.bdf),
PCI_DEV(pr.bdf), pr.pin, apicid,
pr.pirq + 16);
intsrc_entries++;
cell += sizeof(struct pirq_routing) / sizeof(u32);
}
return 0;
}
static void mptable_add_lintsrc(struct mp_config_table *mc, int bus_isa)
{
mp_write_lintsrc(mc, MP_EXTINT,
MP_IRQ_TRIGGER_EDGE | MP_IRQ_POLARITY_HIGH,
bus_isa, 0, MP_APIC_ALL, 0);
mp_write_lintsrc(mc, MP_NMI,
MP_IRQ_TRIGGER_EDGE | MP_IRQ_POLARITY_HIGH,
bus_isa, 0, MP_APIC_ALL, 1);
}
u32 write_mp_table(u32 addr)
{
struct mp_config_table *mc;
int ioapic_id, ioapic_ver;
int bus_isa = 0xff;
int ret;
u32 end;
/* 16 byte align the table address */
addr = ALIGN(addr, 16);
/* Write floating table */
mc = mp_write_floating_table((struct mp_floating_table *)addr);
/* Write configuration table header */
mp_config_table_init(mc);
/* Write processor entry */
mp_write_processor(mc);
/* Write bus entry */
mp_write_bus(mc, bus_isa, BUSTYPE_ISA);
/* Write I/O APIC entry */
ioapic_id = io_apic_read(IO_APIC_ID) >> 24;
ioapic_ver = io_apic_read(IO_APIC_VER) & 0xff;
mp_write_ioapic(mc, ioapic_id, ioapic_ver, IO_APIC_ADDR);
/* Write I/O interrupt assignment entry */
ret = mptable_add_intsrc(mc, bus_isa, ioapic_id);
if (ret)
debug("Failed to write I/O interrupt assignment table\n");
/* Write local interrupt assignment entry */
mptable_add_lintsrc(mc, bus_isa);
/* Finalize the MP table */
end = mptable_finalize(mc);
return end;
}

View file

@ -6,6 +6,7 @@
#include <common.h>
#include <asm/sfi.h>
#include <asm/mpspec.h>
#include <asm/tables.h>
u8 table_compute_checksum(void *v, int len)
@ -20,6 +21,20 @@ u8 table_compute_checksum(void *v, int len)
return checksum;
}
void table_fill_string(char *dest, const char *src, size_t n, char pad)
{
int start, len;
int i;
strncpy(dest, src, n);
/* Fill the remaining bytes with pad */
len = strlen(src);
start = len < n ? len : n;
for (i = start; i < n; i++)
dest[i] = pad;
}
void write_tables(void)
{
u32 __maybe_unused rom_table_end = ROM_TABLE_ADDR;
@ -32,4 +47,8 @@ void write_tables(void)
rom_table_end = write_sfi_table(rom_table_end);
rom_table_end = ALIGN(rom_table_end, 1024);
#endif
#ifdef CONFIG_GENERATE_MP_TABLE
rom_table_end = write_mp_table(rom_table_end);
rom_table_end = ALIGN(rom_table_end, 1024);
#endif
}

View file

@ -273,6 +273,8 @@ int setup_zimage(struct boot_params *setup_base, char *cmd_line, int auto_boot,
build_command_line(cmd_line, auto_boot);
}
setup_video(&setup_base->screen_info);
return 0;
}

View file

@ -0,0 +1,6 @@
DB_88F6820_GP BOARD
M: Stefan Roese <sr@denx.de>
S: Maintained
F: board/Marvell/db-88f6820-gp/
F: include/configs/db-88f6820-gp.h
F: configs/db-88f6820-gp_defconfig

View file

@ -22,7 +22,6 @@ config BOARD_SPECIFIC_OPTIONS # dummy
select NORTHBRIDGE_INTEL_IVYBRIDGE
select SOUTHBRIDGE_INTEL_C216
select HAVE_ACPI_RESUME
select MARK_GRAPHICS_MEM_WRCOMB
select BOARD_ROMSIZE_KB_8192
config PCIE_ECAM_BASE

View file

@ -23,7 +23,6 @@ config BOARD_SPECIFIC_OPTIONS # dummy
select NORTHBRIDGE_INTEL_IVYBRIDGE
select SOUTHBRIDGE_INTEL_C216
select HAVE_ACPI_RESUME
select MARK_GRAPHICS_MEM_WRCOMB
select BOARD_ROMSIZE_KB_8192
config SYS_CAR_ADDR

View file

@ -14,3 +14,4 @@ M: Przemyslaw Marczak <p.marczak@samsung.com>
S: Maintained
F: board/samsung/smdk5420/
F: include/configs/odroid_xu3.h
F: configs/odroid-xu3_defconfig

View file

@ -1,3 +1,4 @@
STM32F429-DISCOVERY BOARD
M: Kamil Lulko <rev13@wp.pl>
S: Maintained
F: board/st/stm32f429-discovery/

View file

@ -55,12 +55,20 @@ int board_eth_enable(void)
return 0;
}
int board_qspi_enable(void)
{
stv0991_pinmux_config(QSPI_CS_CLK_PAD);
clock_setup(QSPI_CLOCK_CFG);
return 0;
}
/*
* Miscellaneous platform dependent initialisations
*/
int board_init(void)
{
board_eth_enable();
board_qspi_enable();
return 0;
}

View file

@ -244,8 +244,8 @@ const struct pad_conf_entry core_padconf_array_essential[] = {
{SPI2_D1, (M14 | PIN_INPUT_PULLDOWN)}, /* spi2_d1.gpio7_15 */
{SPI2_D0, (M14 | PIN_INPUT_PULLUP)}, /* spi2_d0.gpio7_16 */
{SPI2_CS0, (M14 | PIN_INPUT_PULLUP | SLEWCONTROL)}, /* spi2_cs0.gpio7_17 */
{DCAN1_TX, (M0 | PIN_INPUT_PULLUP | SLEWCONTROL)}, /* dcan1_tx.dcan1_tx */
{DCAN1_RX, (M0 | PIN_INPUT_PULLUP | SLEWCONTROL)}, /* dcan1_rx.dcan1_rx */
{DCAN1_TX, (M15 | PULL_UP)}, /* dcan1_tx.safe for dcan1_tx */
{DCAN1_RX, (M15 | PULL_UP)}, /* dcan1_rx.safe for dcan1_rx */
{UART1_RXD, (M0 | PIN_INPUT_SLEW)}, /* uart1_rxd.uart1_rxd */
{UART1_TXD, (M0 | PIN_INPUT_SLEW)}, /* uart1_txd.uart1_txd */
{UART1_CTSN, (M15 | PIN_INPUT_PULLDOWN)}, /* uart1_ctsn.Driveroff */

View file

@ -359,7 +359,7 @@ const struct pad_conf_entry dra74x_core_padconf_array[] = {
{SPI2_D1, (M1 | PIN_INPUT_SLEW)}, /* spi2_d1.uart3_txd */
{SPI2_D0, (M1 | PIN_INPUT_SLEW)}, /* spi2_d0.uart3_ctsn */
{SPI2_CS0, (M1 | PIN_INPUT_PULLUP | SLEWCONTROL)}, /* spi2_cs0.uart3_rtsn */
{DCAN1_TX, (M0 | PIN_INPUT_PULLUP | SLEWCONTROL)}, /* dcan1_tx.dcan1_tx */
{DCAN1_TX, (M15 | PULL_UP)}, /* dcan1_tx.safe for dcan1_tx */
{DCAN1_RX, (M14 | PIN_INPUT_PULLUP | SLEWCONTROL)}, /* dcan1_rx.gpio1_15 */
{UART1_RXD, (M0 | PIN_INPUT_PULLUP | SLEWCONTROL)}, /* uart1_rxd.uart1_rxd */
{UART1_TXD, (M0 | PIN_INPUT_PULLUP | SLEWCONTROL)}, /* uart1_txd.uart1_txd */
@ -371,7 +371,7 @@ const struct pad_conf_entry dra74x_core_padconf_array[] = {
{UART2_RTSN, (M3 | PIN_INPUT_PULLUP)}, /* uart2_rtsn.mmc4_dat3 */
{I2C2_SDA, (M0 | PIN_INPUT_PULLUP)}, /* i2c2_sda.i2c2_sda */
{I2C2_SCL, (M0 | PIN_INPUT_PULLUP)}, /* i2c2_scl.i2c2_scl */
{WAKEUP0, (M1 | PIN_OUTPUT)}, /* Wakeup0.dcan1_rx */
{WAKEUP0, (M15 | PULL_UP)}, /* Wakeup0.safe for dcan1_rx */
{WAKEUP2, (M14 | PIN_OUTPUT)}, /* Wakeup2.gpio1_2 */
};

View file

@ -184,6 +184,8 @@ void am33xx_spl_board_init(void)
*/
i2c_set_bus_num(1);
printf("I2C speed: %d Hz\n", CONFIG_SYS_OMAP24_I2C_SPEED);
if (i2c_probe(TPS65910_CTRL_I2C_ADDR)) {
puts("i2c: cannot access TPS65910\n");
return;

View file

@ -753,6 +753,9 @@ static init_fnc_t init_sequence_f[] = {
#ifdef CONFIG_OF_CONTROL
fdtdec_setup,
#endif
#if defined(CONFIG_X86) && defined(CONFIG_HAVE_FSP)
x86_fsp_init,
#endif
#ifdef CONFIG_TRACE
trace_early_init,
#endif

View file

@ -9,6 +9,7 @@
#include <command.h>
#include <cpu.h>
#include <dm.h>
#include <errno.h>
static const char *cpu_feature_name[CPU_FEAT_COUNT] = {
"L1 cache",

View file

@ -37,7 +37,7 @@ static int do_date(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
int old_bus __maybe_unused;
/* switch to correct I2C bus */
#ifdef CONFIG_DM_I2C
#ifdef CONFIG_DM_RTC
struct udevice *dev;
rcode = uclass_get_device(UCLASS_RTC, 0, &dev);
@ -57,7 +57,7 @@ static int do_date(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
case 2: /* set date & time */
if (strcmp(argv[1],"reset") == 0) {
puts ("Reset RTC...\n");
#ifdef CONFIG_DM_I2C
#ifdef CONFIG_DM_RTC
rcode = dm_rtc_reset(dev);
if (!rcode)
rcode = dm_rtc_set(dev, &default_tm);
@ -69,7 +69,7 @@ static int do_date(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
puts("## Failed to set date after RTC reset\n");
} else {
/* initialize tm with current time */
#ifdef CONFIG_DM_I2C
#ifdef CONFIG_DM_RTC
rcode = dm_rtc_get(dev, &tm);
#else
rcode = rtc_get(&tm);
@ -81,7 +81,7 @@ static int do_date(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
break;
}
/* and write to RTC */
#ifdef CONFIG_DM_I2C
#ifdef CONFIG_DM_RTC
rcode = dm_rtc_set(dev, &tm);
#else
rcode = rtc_set(&tm);
@ -96,7 +96,7 @@ static int do_date(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
}
/* FALL TROUGH */
case 1: /* get date & time */
#ifdef CONFIG_DM_I2C
#ifdef CONFIG_DM_RTC
rcode = dm_rtc_get(dev, &tm);
#else
rcode = rtc_get(&tm);
@ -120,7 +120,7 @@ static int do_date(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
/* switch back to original I2C bus */
#ifdef CONFIG_SYS_I2C
i2c_set_bus_num(old_bus);
#elif !defined(CONFIG_DM_I2C)
#elif !defined(CONFIG_DM_RTC)
I2C_SET_BUS(old_bus);
#endif

View file

@ -368,7 +368,7 @@ static ulong scsi_read(int device, lbaint_t blknr, lbaint_t blkcnt,
{
lbaint_t start, blks;
uintptr_t buf_addr;
unsigned short smallblks;
unsigned short smallblks = 0;
ccb* pccb=(ccb *)&tempccb;
device&=0xff;
/* Setup device
@ -391,7 +391,7 @@ static ulong scsi_read(int device, lbaint_t blknr, lbaint_t blkcnt,
scsi_setup_read16(pccb, start, blocks);
start += blocks;
blks -= blocks;
} else
} else
#endif
if (blks > SCSI_MAX_READ_BLK) {
pccb->datalen=scsi_dev_desc[device].blksz * SCSI_MAX_READ_BLK;

View file

@ -303,8 +303,12 @@ static int do_spi_flash_read_write(int argc, char * const argv[])
else
ret = spi_flash_write(flash, offset, len, buf);
printf("SF: %zu bytes @ %#x %s: %s\n", (size_t)len, (u32)offset,
read ? "Read" : "Written", ret ? "ERROR" : "OK");
printf("SF: %zu bytes @ %#x %s: ", (size_t)len, (u32)offset,
read ? "Read" : "Written");
if (ret)
printf("ERROR %d\n", ret);
else
printf("OK\n");
}
unmap_physmem(buf, len);

View file

@ -3,9 +3,9 @@ CONFIG_TARGET_AM335X_BALTOS=y
CONFIG_SPL=y
CONFIG_SPL_STACK_R=y
CONFIG_SPL_STACK_R_ADDR=0x82000000
CONFIG_FIT=y
CONFIG_FIT_VERBOSE=y
CONFIG_SYS_EXTRA_OPTIONS="NAND"
CONFIG_CONS_INDEX=1
# CONFIG_CMD_IMLS is not set
# CONFIG_CMD_FLASH is not set
# CONFIG_CMD_SETEXPR is not set
# CONFIG_CMD_NET is not set

View file

@ -2,4 +2,5 @@ CONFIG_BLACKFIN=y
CONFIG_TARGET_BF533_STAMP=y
# CONFIG_CMD_SETEXPR is not set
CONFIG_CC_OPTIMIZE_LIBS_FOR_SPEED=y
# CONFIG_REGEX is not set
CONFIG_LIB_RAND=y

View file

@ -2,4 +2,5 @@ CONFIG_BLACKFIN=y
CONFIG_TARGET_BF538F_EZKIT=y
# CONFIG_CMD_SETEXPR is not set
CONFIG_CC_OPTIMIZE_LIBS_FOR_SPEED=y
# CONFIG_REGEX is not set
CONFIG_LIB_RAND=y

View file

@ -3,6 +3,7 @@ CONFIG_VENDOR_GOOGLE=y
CONFIG_DEFAULT_DEVICE_TREE="chromebook_link"
CONFIG_TARGET_CHROMEBOOK_LINK=y
CONFIG_HAVE_MRC=y
CONFIG_HAVE_VGA_BIOS=y
# CONFIG_CMD_IMLS is not set
# CONFIG_CMD_FLASH is not set
# CONFIG_CMD_SETEXPR is not set

View file

@ -3,6 +3,7 @@ CONFIG_VENDOR_GOOGLE=y
CONFIG_DEFAULT_DEVICE_TREE="chromebox_panther"
CONFIG_TARGET_CHROMEBOX_PANTHER=y
CONFIG_HAVE_MRC=y
CONFIG_HAVE_VGA_BIOS=y
# CONFIG_CMD_IMLS is not set
# CONFIG_CMD_FLASH is not set
# CONFIG_CMD_SETEXPR is not set

View file

@ -2,4 +2,5 @@ CONFIG_BLACKFIN=y
CONFIG_TARGET_CM_BF548=y
# CONFIG_CMD_SETEXPR is not set
CONFIG_CC_OPTIMIZE_LIBS_FOR_SPEED=y
# CONFIG_REGEX is not set
CONFIG_LIB_RAND=y

View file

@ -2,7 +2,12 @@ CONFIG_X86=y
CONFIG_VENDOR_INTEL=y
CONFIG_DEFAULT_DEVICE_TREE="crownbay"
CONFIG_TARGET_CROWNBAY=y
CONFIG_SMP=y
CONFIG_MAX_CPUS=2
CONFIG_HAVE_VGA_BIOS=y
CONFIG_GENERATE_PIRQ_TABLE=y
CONFIG_GENERATE_MP_TABLE=y
CONFIG_CMD_CPU=y
# CONFIG_CMD_IMLS is not set
# CONFIG_CMD_FLASH is not set
# CONFIG_CMD_SETEXPR is not set
@ -11,6 +16,10 @@ CONFIG_BOOTSTAGE=y
CONFIG_BOOTSTAGE_REPORT=y
CONFIG_CMD_BOOTSTAGE=y
CONFIG_OF_CONTROL=y
CONFIG_CPU=y
CONFIG_SPI_FLASH=y
CONFIG_VIDEO_VESA=y
CONFIG_FRAMEBUFFER_SET_VESA_MODE=y
CONFIG_DM_RTC=y
CONFIG_USE_PRIVATE_LIBGCC=y
CONFIG_SYS_VSNPRINTF=y

View file

@ -4,6 +4,7 @@ CONFIG_DEFAULT_DEVICE_TREE="minnowmax"
CONFIG_TARGET_MINNOWMAX=y
CONFIG_HAVE_INTEL_ME=y
CONFIG_SMP=y
CONFIG_HAVE_VGA_BIOS=y
CONFIG_GENERATE_SFI_TABLE=y
CONFIG_CMD_CPU=y
# CONFIG_CMD_IMLS is not set
@ -15,6 +16,7 @@ CONFIG_BOOTSTAGE_REPORT=y
CONFIG_CMD_BOOTSTAGE=y
CONFIG_OF_CONTROL=y
CONFIG_CPU=y
CONFIG_DM_PCI=y
CONFIG_SPI_FLASH=y
CONFIG_VIDEO_VESA=y
CONFIG_FRAMEBUFFER_SET_VESA_MODE=y

View file

@ -7,8 +7,8 @@ CONFIG_AUTOBOOT_KEYED=y
CONFIG_AUTOBOOT_PROMPT="Hit SPACE in %d seconds to stop autoboot.\n"
CONFIG_AUTOBOOT_STOP_STR=" "
# CONFIG_CMD_IMLS is not set
# CONFIG_CMD_SAVEENV is not set
# CONFIG_CMD_FLASH is not set
# CONFIG_CMD_SETEXPR is not set
CONFIG_NETDEVICES=y
CONFIG_ETH_DESIGNWARE=y
CONFIG_OF_CONTROL=y

View file

@ -28,7 +28,7 @@ decoupling distro install/boot logic from any knowledge of the bootloader.
This model assumes that boards will load boot configuration files from a
regular storage mechanism (eMMC, SD card, USB Disk, SATA disk, etc.) with
a standard partitioning scheme (MBR, GPT). Boards that cannnot support this
a standard partitioning scheme (MBR, GPT). Boards that cannot support this
storage model are outside the scope of this document, and may still need
board-specific installer/boot-configuration support in a distro.
@ -37,9 +37,9 @@ that contains U-Boot, and that the user has somehow installed U-Boot to this
flash before running the distro installer. Even on boards that do not conform
to this aspect of the model, the extent of the board-specific support in the
distro installer logic would be to install a board-specific U-Boot package to
the boot partition partition during installation. This distro-supplied U-Boot
can still implement the same features as on any other board, and hence the
distro's boot configuration file generation logic can still be board-agnostic.
the boot partition during installation. This distro-supplied U-Boot can still
implement the same features as on any other board, and hence the distro's boot
configuration file generation logic can still be board-agnostic.
Locating Bootable Disks
-----------------------
@ -61,7 +61,7 @@ any other bootloader) will find those boot files and execute them. This is
conceptually identical to creating a grub2 configuration file on a desktop
PC.
Note that in the absense of any partition that is explicitly marked bootable,
Note that in the absence of any partition that is explicitly marked bootable,
U-Boot falls back to searching the first valid partition of a disk for boot
configuration files. Other bootloaders are recommended to do the same, since
I believe that partition table bootable flags aren't so commonly used outside
@ -238,7 +238,7 @@ kernel_addr_r:
The kernel should be located within the first 128M of RAM in order for the
kernel CONFIG_AUTO_ZRELADDR option to work, which is likely enabled on any
distro kernel. Since the kernel will decompress itself to 0x8000 after the
start of RAM, kernel_addr_rshould not overlap that area, or the kernel will
start of RAM, kernel_addr_r should not overlap that area, or the kernel will
have to copy itself somewhere else first before decompression.
A size of 16MB for the kernel is likely adequate.

View file

@ -79,7 +79,7 @@ Find the following files:
* ./northbridge/intel/sandybridge/systemagent-r6.bin
The 3rd one should be renamed to mrc.bin.
As for the video ROM, you can get it here [3].
As for the video ROM, you can get it here [3] and rename it to vga.bin.
Make sure all these binary blobs are put in the board directory.
Now you can build U-Boot and obtain u-boot.rom:
@ -113,6 +113,10 @@ binary using any hex editor (eg: bvi). Go to the offset 0x1fcd8 of the FSP
binary, change the following five bytes values from orginally E8 42 FF FF FF
to B8 00 80 0B 00.
As for the video ROM, you need manually extract it from the Intel provided
BIOS for Crown Bay here [6], using the AMI MMTool [7]. Check PCI option ROM
ID 8086:4108, extract and save it as vga.bin in the board directory.
Now you can build U-Boot and obtain u-boot.rom
$ make crownbay_defconfig
@ -160,6 +164,31 @@ Now you can build U-Boot and obtain u-boot.rom
$ make minnowmax_defconfig
$ make all
Checksums are as follows (but note that newer versions will invalidate this):
$ md5sum -b board/intel/minnowmax/*.bin
ffda9a3b94df5b74323afb328d51e6b4 board/intel/minnowmax/descriptor.bin
69f65b9a580246291d20d08cbef9d7c5 board/intel/minnowmax/fsp.bin
894a97d371544ec21de9c3e8e1716c4b board/intel/minnowmax/me.bin
a2588537da387da592a27219d56e9962 board/intel/minnowmax/vga.bin
The ROM image is broken up into these parts:
Offset Description Controlling config
------------------------------------------------------------
000000 descriptor.bin Hard-coded to 0 in ifdtool
001000 me.bin Set by the descriptor
500000 <spare>
700000 u-boot-dtb.bin CONFIG_SYS_TEXT_BASE
790000 vga.bin CONFIG_X86_OPTION_ROM_ADDR
7c0000 fsp.bin CONFIG_FSP_ADDR
7f8000 <spare> (depends on size of fsp.bin)
7fe000 Environment CONFIG_ENV_OFFSET
7ff800 U-Boot 16-bit boot CONFIG_SYS_X86_START16
Overall ROM image size is controlled by CONFIG_ROM_SIZE.
Intel Galileo instructions:
Only one binary blob is needed for Remote Management Unit (RMU) within Intel
@ -254,10 +283,21 @@ If you want to check both consoles, use '-serial stdio'.
CPU Microcode
-------------
Modern CPUs usually require a special bit stream called microcode [6] to be
Modern CPUs usually require a special bit stream called microcode [8] to be
loaded on the processor after power up in order to function properly. U-Boot
has already integrated these as hex dumps in the source tree.
SMP Support
-----------
On a multicore system, U-Boot is executed on the bootstrap processor (BSP).
Additional application processors (AP) can be brought up by U-Boot. In order to
have an SMP kernel to discover all of the available processors, U-Boot needs to
prepare configuration tables which contain the multi-CPUs information before
loading the OS kernel. Currently U-Boot supports generating two types of tables
for SMP, called Simple Firmware Interface (SFI) [9] and Multi-Processor (MP)
[10] tables. The writing of these two tables are controlled by two Kconfig
options GENERATE_SFI_TABLE and GENERATE_MP_TABLE.
Driver Model
------------
x86 has been converted to use driver model for serial and GPIO.
@ -361,4 +401,8 @@ References
[3] http://www.coreboot.org/~stepan/pci8086,0166.rom
[4] http://www.intel.com/content/www/us/en/embedded/design-tools/evaluation-platforms/atom-e660-eg20t-development-kit.html
[5] http://www.intel.com/fsp
[6] http://en.wikipedia.org/wiki/Microcode
[6] http://www.intel.com/content/www/us/en/secure/intelligent-systems/privileged/e6xx-35-b1-cmc22211.html
[7] http://www.ami.com/products/bios-uefi-tools-and-utilities/bios-uefi-utilities/
[8] http://en.wikipedia.org/wiki/Microcode
[9] http://simplefirmware.org
[10] http://www.intel.com/design/archives/processors/pro/docs/242016.htm

View file

@ -0,0 +1,28 @@
Cadence QSPI controller device tree bindings
--------------------------------------------
Required properties:
- compatible : should be "cadence,qspi".
- reg : 1.Physical base address and size of SPI registers map.
2. Physical base address & size of NOR Flash.
- clocks : Clock phandles (see clock bindings for details).
- sram-size : spi controller sram size.
- status : enable in requried dts.
connected flash properties
--------------------------
- spi-max-frequency : Max supported spi frequency.
- page-size : Flash page size.
- block-size : Flash memory block size.
- tshsl-ns : Added delay in master reference clocks (ref_clk) for
the length that the master mode chip select outputs
are de-asserted between transactions.
- tsd2d-ns : Delay in master reference clocks (ref_clk) between one
chip select being de-activated and the activation of
another.
- tchsh-ns : Delay in master reference clocks between last bit of
current transaction and de-asserting the device chip
select (n_ss_out).
- tslch-ns : Delay in master reference clocks between setting
n_ss_out low and first bit transfer

View file

@ -6,7 +6,6 @@
#
obj-$(CONFIG_SCSI_AHCI) += ahci.o
obj-$(CONFIG_ATA_PIIX) += ata_piix.o
obj-$(CONFIG_DWC_AHSATA) += dwc_ahsata.o
obj-$(CONFIG_FSL_SATA) += fsl_sata.o
obj-$(CONFIG_IDE_FTIDE020) += ftide020.o

View file

@ -43,13 +43,13 @@ u16 *ataid[AHCI_MAX_PORTS];
#define WAIT_MS_FLUSH 5000
#define WAIT_MS_LINKUP 200
static inline u32 ahci_port_base(u32 base, u32 port)
static inline void __iomem *ahci_port_base(void __iomem *base, u32 port)
{
return base + 0x100 + (port * 0x80);
}
static void ahci_setup_port(struct ahci_ioports *port, unsigned long base,
static void ahci_setup_port(struct ahci_ioports *port, void __iomem *base,
unsigned int port_idx)
{
base = ahci_port_base(base, port_idx);
@ -61,7 +61,7 @@ static void ahci_setup_port(struct ahci_ioports *port, unsigned long base,
#define msleep(a) udelay(a * 1000)
static void ahci_dcache_flush_range(unsigned begin, unsigned len)
static void ahci_dcache_flush_range(unsigned long begin, unsigned long len)
{
const unsigned long start = begin;
const unsigned long end = start + len;
@ -75,7 +75,7 @@ static void ahci_dcache_flush_range(unsigned begin, unsigned len)
* controller is invalidated from dcache; next access comes from
* physical RAM.
*/
static void ahci_dcache_invalidate_range(unsigned begin, unsigned len)
static void ahci_dcache_invalidate_range(unsigned long begin, unsigned long len)
{
const unsigned long start = begin;
const unsigned long end = start + len;
@ -94,7 +94,7 @@ static void ahci_dcache_flush_sata_cmd(struct ahci_ioports *pp)
AHCI_PORT_PRIV_DMA_SZ);
}
static int waiting_for_cmd_completed(volatile u8 *offset,
static int waiting_for_cmd_completed(void __iomem *offset,
int timeout_msec,
u32 sign)
{
@ -111,7 +111,7 @@ int __weak ahci_link_up(struct ahci_probe_ent *probe_ent, u8 port)
{
u32 tmp;
int j = 0;
u8 *port_mmio = (u8 *)probe_ent->port[port].port_mmio;
void __iomem *port_mmio = probe_ent->port[port].port_mmio;
/*
* Bring up SATA link.
@ -131,7 +131,7 @@ int __weak ahci_link_up(struct ahci_probe_ent *probe_ent, u8 port)
#ifdef CONFIG_SUNXI_AHCI
/* The sunxi AHCI controller requires this undocumented setup */
static void sunxi_dma_init(volatile u8 *port_mmio)
static void sunxi_dma_init(void __iomem *port_mmio)
{
clrsetbits_le32(port_mmio + PORT_P0DMACR, 0x0000ff00, 0x00004400);
}
@ -171,10 +171,10 @@ static int ahci_host_init(struct ahci_probe_ent *probe_ent)
u16 tmp16;
unsigned short vendor;
#endif
volatile u8 *mmio = (volatile u8 *)probe_ent->mmio_base;
void __iomem *mmio = probe_ent->mmio_base;
u32 tmp, cap_save, cmd;
int i, j, ret;
volatile u8 *port_mmio;
void __iomem *port_mmio;
u32 port_map;
debug("ahci_host_init: start\n");
@ -215,9 +215,9 @@ static int ahci_host_init(struct ahci_probe_ent *probe_ent)
for (i = 0; i < probe_ent->n_ports; i++) {
if (!(port_map & (1 << i)))
continue;
probe_ent->port[i].port_mmio = ahci_port_base((u32) mmio, i);
probe_ent->port[i].port_mmio = ahci_port_base(mmio, i);
port_mmio = (u8 *) probe_ent->port[i].port_mmio;
ahci_setup_port(&probe_ent->port[i], (unsigned long)mmio, i);
ahci_setup_port(&probe_ent->port[i], mmio, i);
/* make sure port is not active */
tmp = readl(port_mmio + PORT_CMD);
@ -299,9 +299,6 @@ static int ahci_host_init(struct ahci_probe_ent *probe_ent)
writel(1 << i, mmio + HOST_IRQ_STAT);
/* set irq mask (enables interrupts) */
writel(DEF_PORT_IRQ, port_mmio + PORT_IRQ_MASK);
/* register linkup ports */
tmp = readl(port_mmio + PORT_SCR_STAT);
debug("SATA port %d status: 0x%x\n", i, tmp);
@ -329,7 +326,7 @@ static void ahci_print_info(struct ahci_probe_ent *probe_ent)
pci_dev_t pdev = probe_ent->dev;
u16 cc;
#endif
volatile u8 *mmio = (volatile u8 *)probe_ent->mmio_base;
void __iomem *mmio = probe_ent->mmio_base;
u32 vers, cap, cap2, impl, speed;
const char *speed_s;
const char *scc_s;
@ -462,7 +459,7 @@ static int ahci_fill_sg(u8 port, unsigned char *buf, int buf_len)
for (i = 0; i < sg_count; i++) {
ahci_sg->addr =
cpu_to_le32((u32) buf + i * MAX_DATA_BYTE_COUNT);
cpu_to_le32((unsigned long) buf + i * MAX_DATA_BYTE_COUNT);
ahci_sg->addr_hi = 0;
ahci_sg->flags_size = cpu_to_le32(0x3fffff &
(buf_len < MAX_DATA_BYTE_COUNT
@ -480,8 +477,11 @@ static void ahci_fill_cmd_slot(struct ahci_ioports *pp, u32 opts)
{
pp->cmd_slot->opts = cpu_to_le32(opts);
pp->cmd_slot->status = 0;
pp->cmd_slot->tbl_addr = cpu_to_le32(pp->cmd_tbl & 0xffffffff);
pp->cmd_slot->tbl_addr_hi = 0;
pp->cmd_slot->tbl_addr = cpu_to_le32((u32)pp->cmd_tbl & 0xffffffff);
#ifdef CONFIG_PHYS_64BIT
pp->cmd_slot->tbl_addr_hi =
cpu_to_le32((u32)(((pp->cmd_tbl) >> 16) >> 16));
#endif
}
@ -489,7 +489,7 @@ static void ahci_fill_cmd_slot(struct ahci_ioports *pp, u32 opts)
static void ahci_set_feature(u8 port)
{
struct ahci_ioports *pp = &(probe_ent->port[port]);
volatile u8 *port_mmio = (volatile u8 *)pp->port_mmio;
void __iomem *port_mmio = pp->port_mmio;
u32 cmd_fis_len = 5; /* five dwords */
u8 fis[20];
@ -514,7 +514,7 @@ static void ahci_set_feature(u8 port)
}
#endif
static int wait_spinup(volatile u8 *port_mmio)
static int wait_spinup(void __iomem *port_mmio)
{
ulong start;
u32 tf_data;
@ -532,9 +532,9 @@ static int wait_spinup(volatile u8 *port_mmio)
static int ahci_port_start(u8 port)
{
struct ahci_ioports *pp = &(probe_ent->port[port]);
volatile u8 *port_mmio = (volatile u8 *)pp->port_mmio;
void __iomem *port_mmio = pp->port_mmio;
u32 port_status;
u32 mem;
void __iomem *mem;
debug("Enter start port: %d\n", port);
port_status = readl(port_mmio + PORT_SCR_STAT);
@ -544,15 +544,16 @@ static int ahci_port_start(u8 port)
return -1;
}
mem = (u32) malloc(AHCI_PORT_PRIV_DMA_SZ + 2048);
mem = malloc(AHCI_PORT_PRIV_DMA_SZ + 2048);
if (!mem) {
free(pp);
printf("%s: No mem for table!\n", __func__);
return -ENOMEM;
}
mem = (mem + 0x800) & (~0x7ff); /* Aligned to 2048-bytes */
memset((u8 *) mem, 0, AHCI_PORT_PRIV_DMA_SZ);
/* Aligned to 2048-bytes */
mem = memalign(2048, AHCI_PORT_PRIV_DMA_SZ);
memset(mem, 0, AHCI_PORT_PRIV_DMA_SZ);
/*
* First item in chunk of DMA memory: 32-slot command table,
@ -560,7 +561,7 @@ static int ahci_port_start(u8 port)
*/
pp->cmd_slot =
(struct ahci_cmd_hdr *)(uintptr_t)virt_to_phys((void *)mem);
debug("cmd_slot = 0x%x\n", (unsigned)pp->cmd_slot);
debug("cmd_slot = %p\n", pp->cmd_slot);
mem += (AHCI_CMD_SLOT_SZ + 224);
/*
@ -574,13 +575,14 @@ static int ahci_port_start(u8 port)
* and its scatter-gather table
*/
pp->cmd_tbl = virt_to_phys((void *)mem);
debug("cmd_tbl_dma = 0x%x\n", pp->cmd_tbl);
debug("cmd_tbl_dma = %lx\n", pp->cmd_tbl);
mem += AHCI_CMD_TBL_HDR;
pp->cmd_tbl_sg =
(struct ahci_sg *)(uintptr_t)virt_to_phys((void *)mem);
writel_with_flush((u32) pp->cmd_slot, port_mmio + PORT_LST_ADDR);
writel_with_flush((unsigned long)pp->cmd_slot,
port_mmio + PORT_LST_ADDR);
writel_with_flush(pp->rx_fis, port_mmio + PORT_FIS_ADDR);
@ -607,7 +609,7 @@ static int ahci_device_data_io(u8 port, u8 *fis, int fis_len, u8 *buf,
{
struct ahci_ioports *pp = &(probe_ent->port[port]);
volatile u8 *port_mmio = (volatile u8 *)pp->port_mmio;
void __iomem *port_mmio = pp->port_mmio;
u32 opts;
u32 port_status;
int sg_count;
@ -632,7 +634,7 @@ static int ahci_device_data_io(u8 port, u8 *fis, int fis_len, u8 *buf,
ahci_fill_cmd_slot(pp, opts);
ahci_dcache_flush_sata_cmd(pp);
ahci_dcache_flush_range((unsigned)buf, (unsigned)buf_len);
ahci_dcache_flush_range((unsigned long)buf, (unsigned long)buf_len);
writel_with_flush(1, port_mmio + PORT_CMD_ISSUE);
@ -642,7 +644,8 @@ static int ahci_device_data_io(u8 port, u8 *fis, int fis_len, u8 *buf,
return -1;
}
ahci_dcache_invalidate_range((unsigned)buf, (unsigned)buf_len);
ahci_dcache_invalidate_range((unsigned long)buf,
(unsigned long)buf_len);
debug("%s: %d byte transferred.\n", __func__, pp->cmd_slot->status);
return 0;
@ -1026,7 +1029,7 @@ static int ata_io_flush(u8 port)
{
u8 fis[20];
struct ahci_ioports *pp = &(probe_ent->port[port]);
volatile u8 *port_mmio = (volatile u8 *)pp->port_mmio;
void __iomem *port_mmio = pp->port_mmio;
u32 cmd_fis_len = 5; /* five dwords */
/* Preset the FIS */

View file

@ -1,717 +0,0 @@
/*
* Copyright (C) Procsys. All rights reserved.
* Author: Mushtaq Khan <mushtaq_k@procsys.com>
* <mushtaqk_921@yahoo.co.in>
*
* SPDX-License-Identifier: GPL-2.0+
*
* with the reference to ata_piix driver in kernel 2.4.32
*/
/*
* This file contains SATA controller and SATA drive initialization functions
*/
#include <common.h>
#include <asm/io.h>
#include <pci.h>
#include <command.h>
#include <config.h>
#include <asm/byteorder.h>
#include <part.h>
#include <ide.h>
#include <ata.h>
#include <sata.h>
#define DEBUG_SATA 0 /* For debug prints set DEBUG_SATA to 1 */
#define SATA_DECL
#define DRV_DECL /* For file specific declarations */
#include "ata_piix.h"
/* Macros realted to PCI */
#define PCI_SATA_BUS 0x00
#define PCI_SATA_DEV 0x1f
#define PCI_SATA_FUNC 0x02
#define PCI_SATA_BASE1 0x10
#define PCI_SATA_BASE2 0x14
#define PCI_SATA_BASE3 0x18
#define PCI_SATA_BASE4 0x1c
#define PCI_SATA_BASE5 0x20
#define PCI_PMR 0x90
#define PCI_PI 0x09
#define PCI_PCS 0x92
#define PCI_DMA_CTL 0x48
#define PORT_PRESENT (1<<0)
#define PORT_ENABLED (1<<4)
u32 bdf;
u32 iobase1; /* Primary cmd block */
u32 iobase2; /* Primary ctl block */
u32 iobase3; /* Sec cmd block */
u32 iobase4; /* sec ctl block */
u32 iobase5; /* BMDMA*/
int pci_sata_init(void)
{
u32 bus = PCI_SATA_BUS;
u32 dev = PCI_SATA_DEV;
u32 fun = PCI_SATA_FUNC;
u16 cmd = 0;
u8 lat = 0, pcibios_max_latency = 0xff;
u8 pmr; /* Port mapping reg */
u8 pi; /* Prgming Interface reg */
bdf = PCI_BDF(bus, dev, fun);
pci_read_config_dword(bdf, PCI_SATA_BASE1, &iobase1);
pci_read_config_dword(bdf, PCI_SATA_BASE2, &iobase2);
pci_read_config_dword(bdf, PCI_SATA_BASE3, &iobase3);
pci_read_config_dword(bdf, PCI_SATA_BASE4, &iobase4);
pci_read_config_dword(bdf, PCI_SATA_BASE5, &iobase5);
if ((iobase1 == 0xFFFFFFFF) || (iobase2 == 0xFFFFFFFF) ||
(iobase3 == 0xFFFFFFFF) || (iobase4 == 0xFFFFFFFF) ||
(iobase5 == 0xFFFFFFFF)) {
/* ERROR */
printf("error no base addr for SATA controller\n");
return 1;
}
iobase1 &= 0xFFFFFFFE;
iobase2 &= 0xFFFFFFFE;
iobase3 &= 0xFFFFFFFE;
iobase4 &= 0xFFFFFFFE;
iobase5 &= 0xFFFFFFFE;
/* check for mode */
pci_read_config_byte(bdf, PCI_PMR, &pmr);
if (pmr > 1) {
puts("combined mode not supported\n");
return 1;
}
pci_read_config_byte(bdf, PCI_PI, &pi);
if ((pi & 0x05) != 0x05) {
puts("Sata is in Legacy mode\n");
return 1;
} else
puts("sata is in Native mode\n");
/* MASTER CFG AND IO CFG */
pci_read_config_word(bdf, PCI_COMMAND, &cmd);
cmd |= PCI_COMMAND_MASTER | PCI_COMMAND_IO;
pci_write_config_word(bdf, PCI_COMMAND, cmd);
pci_read_config_byte(dev, PCI_LATENCY_TIMER, &lat);
if (lat < 16)
lat = (64 <= pcibios_max_latency) ? 64 : pcibios_max_latency;
else if (lat > pcibios_max_latency)
lat = pcibios_max_latency;
pci_write_config_byte(dev, PCI_LATENCY_TIMER, lat);
return 0;
}
int sata_bus_probe(int port_no)
{
int orig_mask, mask;
u16 pcs;
mask = (PORT_PRESENT << port_no);
pci_read_config_word(bdf, PCI_PCS, &pcs);
orig_mask = (int) pcs & 0xff;
if ((orig_mask & mask) != mask)
return 0;
else
return 1;
}
int init_sata(int dev)
{
static int done;
u8 i, rv = 0;
if (!done)
done = 1;
else
return 0;
rv = pci_sata_init();
if (rv == 1) {
puts("pci initialization failed\n");
return 1;
}
port[0].port_no = 0;
port[0].ioaddr.cmd_addr = iobase1;
port[0].ioaddr.altstatus_addr = port[0].ioaddr.ctl_addr =
iobase2 | ATA_PCI_CTL_OFS;
port[0].ioaddr.bmdma_addr = iobase5;
port[1].port_no = 1;
port[1].ioaddr.cmd_addr = iobase3;
port[1].ioaddr.altstatus_addr = port[1].ioaddr.ctl_addr =
iobase4 | ATA_PCI_CTL_OFS;
port[1].ioaddr.bmdma_addr = iobase5 + 0x8;
for (i = 0; i < CONFIG_SYS_SATA_MAXBUS; i++)
sata_port(&port[i].ioaddr);
for (i = 0; i < CONFIG_SYS_SATA_MAXBUS; i++) {
if (!(sata_bus_probe(i))) {
port[i].port_state = 0;
printf("SATA#%d port is not present\n", i);
} else {
printf("SATA#%d port is present\n", i);
if (sata_bus_softreset(i))
port[i].port_state = 0;
else
port[i].port_state = 1;
}
}
for (i = 0; i < CONFIG_SYS_SATA_MAXBUS; i++) {
u8 j, devno;
if (port[i].port_state == 0)
continue;
for (j = 0; j < CONFIG_SYS_SATA_DEVS_PER_BUS; j++) {
sata_identify(i, j);
set_Feature_cmd(i, j);
devno = i * CONFIG_SYS_SATA_DEVS_PER_BUS + j;
if ((sata_dev_desc[devno].lba > 0) &&
(sata_dev_desc[devno].blksz > 0)) {
dev_print(&sata_dev_desc[devno]);
/* initialize partition type */
init_part(&sata_dev_desc[devno]);
}
}
}
return 0;
}
int reset_sata(int dev)
{
return 0;
}
static inline u8 sata_inb(unsigned long ioaddr)
{
return inb(ioaddr);
}
static inline void sata_outb(unsigned char val, unsigned long ioaddr)
{
outb(val, ioaddr);
}
static void output_data(struct sata_ioports *ioaddr, ulong * sect_buf,
int words)
{
outsw(ioaddr->data_addr, sect_buf, words << 1);
}
static int input_data(struct sata_ioports *ioaddr, ulong * sect_buf, int words)
{
insw(ioaddr->data_addr, sect_buf, words << 1);
return 0;
}
static void sata_cpy(unsigned char *dst, unsigned char *src, unsigned int len)
{
unsigned char *end, *last;
last = dst;
end = src + len - 1;
/* reserve space for '\0' */
if (len < 2)
goto OUT;
/* skip leading white space */
while ((*src) && (src < end) && (*src == ' '))
++src;
/* copy string, omitting trailing white space */
while ((*src) && (src < end)) {
*dst++ = *src;
if (*src++ != ' ')
last = dst;
}
OUT:
*last = '\0';
}
int sata_bus_softreset(int num)
{
u8 dev = 0, status = 0, i;
port[num].dev_mask = 0;
for (i = 0; i < CONFIG_SYS_SATA_DEVS_PER_BUS; i++) {
if (!(sata_devchk(&port[num].ioaddr, i))) {
debug("dev_chk failed for dev#%d\n", i);
} else {
port[num].dev_mask |= (1 << i);
debug("dev_chk passed for dev#%d\n", i);
}
}
if (!(port[num].dev_mask)) {
printf("no devices on port%d\n", num);
return 1;
}
dev_select(&port[num].ioaddr, dev);
port[num].ctl_reg = 0x08; /* Default value of control reg */
sata_outb(port[num].ctl_reg, port[num].ioaddr.ctl_addr);
udelay(10);
sata_outb(port[num].ctl_reg | ATA_SRST, port[num].ioaddr.ctl_addr);
udelay(10);
sata_outb(port[num].ctl_reg, port[num].ioaddr.ctl_addr);
/*
* spec mandates ">= 2ms" before checking status.
* We wait 150ms, because that was the magic delay used for
* ATAPI devices in Hale Landis's ATADRVR, for the period of time
* between when the ATA command register is written, and then
* status is checked. Because waiting for "a while" before
* checking status is fine, post SRST, we perform this magic
* delay here as well.
*/
mdelay(150);
status = sata_busy_wait(&port[num].ioaddr, ATA_BUSY, 300);
while ((status & ATA_BUSY)) {
mdelay(100);
status = sata_busy_wait(&port[num].ioaddr, ATA_BUSY, 3);
}
if (status & ATA_BUSY)
printf("ata%u is slow to respond,plz be patient\n", num);
while ((status & ATA_BUSY)) {
mdelay(100);
status = sata_chk_status(&port[num].ioaddr);
}
if (status & ATA_BUSY) {
printf("ata%u failed to respond : bus reset failed\n", num);
return 1;
}
return 0;
}
void sata_identify(int num, int dev)
{
u8 cmd = 0, status = 0;
u8 devno = num * CONFIG_SYS_SATA_DEVS_PER_BUS + dev;
u16 iobuf[ATA_SECT_SIZE];
u64 n_sectors = 0;
u8 mask = 0;
memset(iobuf, 0, sizeof(iobuf));
hd_driveid_t *iop = (hd_driveid_t *) iobuf;
if (dev == 0)
mask = 0x01;
else
mask = 0x02;
if (!(port[num].dev_mask & mask)) {
printf("dev%d is not present on port#%d\n", dev, num);
return;
}
printf("port=%d dev=%d\n", num, dev);
dev_select(&port[num].ioaddr, dev);
status = 0;
cmd = ATA_CMD_IDENT; /* Device Identify Command */
sata_outb(cmd, port[num].ioaddr.command_addr);
sata_inb(port[num].ioaddr.altstatus_addr);
udelay(10);
status = sata_busy_wait(&port[num].ioaddr, ATA_BUSY, 1000);
if (status & ATA_ERR) {
puts("\ndevice not responding\n");
port[num].dev_mask &= ~mask;
return;
}
input_data(&port[num].ioaddr, (ulong *) iobuf, ATA_SECTORWORDS);
debug("\nata%u: dev %u cfg 49:%04x 82:%04x 83:%04x 84:%04x85:%04x"
"86:%04x" "87:%04x 88:%04x\n", num, dev, iobuf[49],
iobuf[82], iobuf[83], iobuf[84], iobuf[85], iobuf[86],
iobuf[87], iobuf[88]);
/* we require LBA and DMA support (bits 8 & 9 of word 49) */
if (!ata_id_has_dma(iobuf) || !ata_id_has_lba(iobuf))
debug("ata%u: no dma/lba\n", num);
ata_dump_id(iobuf);
if (ata_id_has_lba48(iobuf))
n_sectors = ata_id_u64(iobuf, 100);
else
n_sectors = ata_id_u32(iobuf, 60);
debug("no. of sectors %u\n", ata_id_u64(iobuf, 100));
debug("no. of sectors %u\n", ata_id_u32(iobuf, 60));
if (n_sectors == 0) {
port[num].dev_mask &= ~mask;
return;
}
sata_cpy((unsigned char *)sata_dev_desc[devno].revision, iop->fw_rev,
sizeof(sata_dev_desc[devno].revision));
sata_cpy((unsigned char *)sata_dev_desc[devno].vendor, iop->model,
sizeof(sata_dev_desc[devno].vendor));
sata_cpy((unsigned char *)sata_dev_desc[devno].product, iop->serial_no,
sizeof(sata_dev_desc[devno].product));
strswab(sata_dev_desc[devno].revision);
strswab(sata_dev_desc[devno].vendor);
if ((iop->config & 0x0080) == 0x0080)
sata_dev_desc[devno].removable = 1;
else
sata_dev_desc[devno].removable = 0;
sata_dev_desc[devno].lba = iop->lba_capacity;
debug("lba=0x%x", sata_dev_desc[devno].lba);
#ifdef CONFIG_LBA48
if (iop->command_set_2 & 0x0400) {
sata_dev_desc[devno].lba48 = 1;
lba = (unsigned long long) iop->lba48_capacity[0] |
((unsigned long long) iop->lba48_capacity[1] << 16) |
((unsigned long long) iop->lba48_capacity[2] << 32) |
((unsigned long long) iop->lba48_capacity[3] << 48);
} else {
sata_dev_desc[devno].lba48 = 0;
}
#endif
/* assuming HD */
sata_dev_desc[devno].type = DEV_TYPE_HARDDISK;
sata_dev_desc[devno].blksz = ATA_BLOCKSIZE;
sata_dev_desc[devno].log2blksz = LOG2(sata_dev_desc[devno].blksz);
sata_dev_desc[devno].lun = 0; /* just to fill something in... */
}
void set_Feature_cmd(int num, int dev)
{
u8 mask = 0x00, status = 0;
if (dev == 0)
mask = 0x01;
else
mask = 0x02;
if (!(port[num].dev_mask & mask)) {
debug("dev%d is not present on port#%d\n", dev, num);
return;
}
dev_select(&port[num].ioaddr, dev);
sata_outb(SETFEATURES_XFER, port[num].ioaddr.feature_addr);
sata_outb(XFER_PIO_4, port[num].ioaddr.nsect_addr);
sata_outb(0, port[num].ioaddr.lbal_addr);
sata_outb(0, port[num].ioaddr.lbam_addr);
sata_outb(0, port[num].ioaddr.lbah_addr);
sata_outb(ATA_DEVICE_OBS, port[num].ioaddr.device_addr);
sata_outb(ATA_CMD_SETF, port[num].ioaddr.command_addr);
udelay(50);
mdelay(150);
status = sata_busy_wait(&port[num].ioaddr, ATA_BUSY, 5000);
if ((status & (ATA_STAT_BUSY | ATA_STAT_ERR))) {
printf("Error : status 0x%02x\n", status);
port[num].dev_mask &= ~mask;
}
}
void sata_port(struct sata_ioports *ioport)
{
ioport->data_addr = ioport->cmd_addr + ATA_REG_DATA;
ioport->error_addr = ioport->cmd_addr + ATA_REG_ERR;
ioport->feature_addr = ioport->cmd_addr + ATA_REG_FEATURE;
ioport->nsect_addr = ioport->cmd_addr + ATA_REG_NSECT;
ioport->lbal_addr = ioport->cmd_addr + ATA_REG_LBAL;
ioport->lbam_addr = ioport->cmd_addr + ATA_REG_LBAM;
ioport->lbah_addr = ioport->cmd_addr + ATA_REG_LBAH;
ioport->device_addr = ioport->cmd_addr + ATA_REG_DEVICE;
ioport->status_addr = ioport->cmd_addr + ATA_REG_STATUS;
ioport->command_addr = ioport->cmd_addr + ATA_REG_CMD;
}
int sata_devchk(struct sata_ioports *ioaddr, int dev)
{
u8 nsect, lbal;
dev_select(ioaddr, dev);
sata_outb(0x55, ioaddr->nsect_addr);
sata_outb(0xaa, ioaddr->lbal_addr);
sata_outb(0xaa, ioaddr->nsect_addr);
sata_outb(0x55, ioaddr->lbal_addr);
sata_outb(0x55, ioaddr->nsect_addr);
sata_outb(0xaa, ioaddr->lbal_addr);
nsect = sata_inb(ioaddr->nsect_addr);
lbal = sata_inb(ioaddr->lbal_addr);
if ((nsect == 0x55) && (lbal == 0xaa))
return 1; /* we found a device */
else
return 0; /* nothing found */
}
void dev_select(struct sata_ioports *ioaddr, int dev)
{
u8 tmp = 0;
if (dev == 0)
tmp = ATA_DEVICE_OBS;
else
tmp = ATA_DEVICE_OBS | ATA_DEV1;
sata_outb(tmp, ioaddr->device_addr);
sata_inb(ioaddr->altstatus_addr);
udelay(5);
}
u8 sata_busy_wait(struct sata_ioports *ioaddr, int bits, unsigned int max)
{
u8 status;
do {
udelay(1000);
status = sata_chk_status(ioaddr);
max--;
} while ((status & bits) && (max > 0));
return status;
}
u8 sata_chk_status(struct sata_ioports *ioaddr)
{
return sata_inb(ioaddr->status_addr);
}
ulong sata_read(int device, ulong blknr, lbaint_t blkcnt, void *buff)
{
ulong n = 0, *buffer = (ulong *)buff;
u8 dev = 0, num = 0, mask = 0, status = 0;
#ifdef CONFIG_LBA48
unsigned char lba48 = 0;
if (blknr & 0x0000fffff0000000) {
if (!sata_dev_desc[devno].lba48) {
printf("Drive doesn't support 48-bit addressing\n");
return 0;
}
/* more than 28 bits used, use 48bit mode */
lba48 = 1;
}
#endif
/* Port Number */
num = device / CONFIG_SYS_SATA_DEVS_PER_BUS;
/* dev on the port */
if (device >= CONFIG_SYS_SATA_DEVS_PER_BUS)
dev = device - CONFIG_SYS_SATA_DEVS_PER_BUS;
else
dev = device;
if (dev == 0)
mask = 0x01;
else
mask = 0x02;
if (!(port[num].dev_mask & mask)) {
printf("dev%d is not present on port#%d\n", dev, num);
return 0;
}
/* Select device */
dev_select(&port[num].ioaddr, dev);
status = sata_busy_wait(&port[num].ioaddr, ATA_BUSY, 500);
if (status & ATA_BUSY) {
printf("ata%u failed to respond\n", port[num].port_no);
return n;
}
while (blkcnt-- > 0) {
status = sata_busy_wait(&port[num].ioaddr, ATA_BUSY, 500);
if (status & ATA_BUSY) {
printf("ata%u failed to respond\n", 0);
return n;
}
#ifdef CONFIG_LBA48
if (lba48) {
/* write high bits */
sata_outb(0, port[num].ioaddr.nsect_addr);
sata_outb((blknr >> 24) & 0xFF,
port[num].ioaddr.lbal_addr);
sata_outb((blknr >> 32) & 0xFF,
port[num].ioaddr.lbam_addr);
sata_outb((blknr >> 40) & 0xFF,
port[num].ioaddr.lbah_addr);
}
#endif
sata_outb(1, port[num].ioaddr.nsect_addr);
sata_outb(((blknr) >> 0) & 0xFF,
port[num].ioaddr.lbal_addr);
sata_outb((blknr >> 8) & 0xFF, port[num].ioaddr.lbam_addr);
sata_outb((blknr >> 16) & 0xFF, port[num].ioaddr.lbah_addr);
#ifdef CONFIG_LBA48
if (lba48) {
sata_outb(ATA_LBA, port[num].ioaddr.device_addr);
sata_outb(ATA_CMD_READ_EXT,
port[num].ioaddr.command_addr);
} else
#endif
{
sata_outb(ATA_LBA | ((blknr >> 24) & 0xF),
port[num].ioaddr.device_addr);
sata_outb(ATA_CMD_READ,
port[num].ioaddr.command_addr);
}
mdelay(50);
/* may take up to 4 sec */
status = sata_busy_wait(&port[num].ioaddr, ATA_BUSY, 4000);
if ((status & (ATA_STAT_DRQ | ATA_STAT_BUSY | ATA_STAT_ERR))
!= ATA_STAT_DRQ) {
u8 err = 0;
printf("Error no DRQ dev %d blk %ld: sts 0x%02x\n",
device, (ulong) blknr, status);
err = sata_inb(port[num].ioaddr.error_addr);
printf("Error reg = 0x%x\n", err);
return n;
}
input_data(&port[num].ioaddr, buffer, ATA_SECTORWORDS);
sata_inb(port[num].ioaddr.altstatus_addr);
udelay(50);
++n;
++blknr;
buffer += ATA_SECTORWORDS;
}
return n;
}
ulong sata_write(int device, ulong blknr, lbaint_t blkcnt, const void *buff)
{
ulong n = 0, *buffer = (ulong *)buff;
unsigned char status = 0, num = 0, dev = 0, mask = 0;
#ifdef CONFIG_LBA48
unsigned char lba48 = 0;
if (blknr & 0x0000fffff0000000) {
if (!sata_dev_desc[devno].lba48) {
printf("Drive doesn't support 48-bit addressing\n");
return 0;
}
/* more than 28 bits used, use 48bit mode */
lba48 = 1;
}
#endif
/* Port Number */
num = device / CONFIG_SYS_SATA_DEVS_PER_BUS;
/* dev on the Port */
if (device >= CONFIG_SYS_SATA_DEVS_PER_BUS)
dev = device - CONFIG_SYS_SATA_DEVS_PER_BUS;
else
dev = device;
if (dev == 0)
mask = 0x01;
else
mask = 0x02;
/* Select device */
dev_select(&port[num].ioaddr, dev);
status = sata_busy_wait(&port[num].ioaddr, ATA_BUSY, 500);
if (status & ATA_BUSY) {
printf("ata%u failed to respond\n", port[num].port_no);
return n;
}
while (blkcnt-- > 0) {
status = sata_busy_wait(&port[num].ioaddr, ATA_BUSY, 500);
if (status & ATA_BUSY) {
printf("ata%u failed to respond\n",
port[num].port_no);
return n;
}
#ifdef CONFIG_LBA48
if (lba48) {
/* write high bits */
sata_outb(0, port[num].ioaddr.nsect_addr);
sata_outb((blknr >> 24) & 0xFF,
port[num].ioaddr.lbal_addr);
sata_outb((blknr >> 32) & 0xFF,
port[num].ioaddr.lbam_addr);
sata_outb((blknr >> 40) & 0xFF,
port[num].ioaddr.lbah_addr);
}
#endif
sata_outb(1, port[num].ioaddr.nsect_addr);
sata_outb((blknr >> 0) & 0xFF, port[num].ioaddr.lbal_addr);
sata_outb((blknr >> 8) & 0xFF, port[num].ioaddr.lbam_addr);
sata_outb((blknr >> 16) & 0xFF, port[num].ioaddr.lbah_addr);
#ifdef CONFIG_LBA48
if (lba48) {
sata_outb(ATA_LBA, port[num].ioaddr.device_addr);
sata_outb(ATA_CMD_WRITE_EXT,
port[num].ioaddr.command_addr);
} else
#endif
{
sata_outb(ATA_LBA | ((blknr >> 24) & 0xF),
port[num].ioaddr.device_addr);
sata_outb(ATA_CMD_WRITE,
port[num].ioaddr.command_addr);
}
mdelay(50);
/* may take up to 4 sec */
status = sata_busy_wait(&port[num].ioaddr, ATA_BUSY, 4000);
if ((status & (ATA_STAT_DRQ | ATA_STAT_BUSY | ATA_STAT_ERR))
!= ATA_STAT_DRQ) {
printf("Error no DRQ dev %d blk %ld: sts 0x%02x\n",
device, (ulong) blknr, status);
return n;
}
output_data(&port[num].ioaddr, buffer, ATA_SECTORWORDS);
sata_inb(port[num].ioaddr.altstatus_addr);
udelay(50);
++n;
++blknr;
buffer += ATA_SECTORWORDS;
}
return n;
}
int scan_sata(int dev)
{
return 0;
}

View file

@ -1,71 +0,0 @@
#ifndef __ATA_PIIX_H__
#define __ATA_PIIX_H__
struct sata_ioports {
unsigned long cmd_addr;
unsigned long data_addr;
unsigned long error_addr;
unsigned long feature_addr;
unsigned long nsect_addr;
unsigned long lbal_addr;
unsigned long lbam_addr;
unsigned long lbah_addr;
unsigned long device_addr;
unsigned long status_addr;
unsigned long command_addr;
unsigned long altstatus_addr;
unsigned long ctl_addr;
unsigned long bmdma_addr;
unsigned long scr_addr;
};
struct sata_port {
unsigned char port_no; /* primary=0, secondary=1 */
struct sata_ioports ioaddr; /* ATA cmd/ctl/dma reg blks */
unsigned char ctl_reg;
unsigned char last_ctl;
unsigned char port_state; /* 1-port is available and */
/* 0-port is not available */
unsigned char dev_mask;
};
/***********SATA LIBRARY SPECIFIC DEFINITIONS AND DECLARATIONS**************/
#ifdef SATA_DECL /* SATA library specific declarations */
inline void ata_dump_id(u16 *id)
{
debug("49 = 0x%04x "
"53 = 0x%04x "
"63 = 0x%04x "
"64 = 0x%04x "
"75 = 0x%04x\n", id[49], id[53], id[63], id[64], id[75]);
debug("80 = 0x%04x "
"81 = 0x%04x "
"82 = 0x%04x "
"83 = 0x%04x "
"84 = 0x%04x\n", id[80], id[81], id[82], id[83], id[84]);
debug("88 = 0x%04x " "93 = 0x%04x\n", id[88], id[93]);
}
#endif
#ifdef SATA_DECL /*SATA library specific declarations */
int sata_bus_softreset(int num);
void sata_identify(int num, int dev);
void sata_port(struct sata_ioports *ioport);
void set_Feature_cmd(int num, int dev);
int sata_devchk(struct sata_ioports *ioaddr, int dev);
void dev_select(struct sata_ioports *ioaddr, int dev);
u8 sata_busy_wait(struct sata_ioports *ioaddr, int bits, unsigned int max);
u8 sata_chk_status(struct sata_ioports *ioaddr);
#endif
/************DRIVER SPECIFIC DEFINITIONS AND DECLARATIONS**************/
#ifdef DRV_DECL /* Driver specific declaration */
int init_sata(int dev);
#endif
#ifdef DRV_DECL /* Defines Driver Specific variables */
struct sata_port port[CONFIG_SYS_SATA_MAXBUS];
#endif
#endif /* __ATA_PIIX_H__ */

View file

@ -80,7 +80,7 @@ struct sata_host_regs {
static int is_ready;
static inline u32 ahci_port_base(u32 base, u32 port)
static inline void __iomem *ahci_port_base(void __iomem *base, u32 port)
{
return base + 0x100 + (port * 0x80);
}
@ -167,7 +167,7 @@ static int ahci_host_init(struct ahci_probe_ent *probe_ent)
for (i = 0; i < probe_ent->n_ports; i++) {
probe_ent->port[i].port_mmio =
ahci_port_base((u32)host_mmio, i);
ahci_port_base(host_mmio, i);
port_mmio =
(struct sata_port_regs *)probe_ent->port[i].port_mmio;
@ -399,8 +399,11 @@ static void ahci_fill_cmd_slot(struct ahci_ioports *pp, u32 cmd_slot, u32 opts)
memset(cmd_hdr, 0, AHCI_CMD_SLOT_SZ);
cmd_hdr->opts = cpu_to_le32(opts);
cmd_hdr->status = 0;
cmd_hdr->tbl_addr = cpu_to_le32(pp->cmd_tbl & 0xffffffff);
cmd_hdr->tbl_addr_hi = 0;
pp->cmd_slot->tbl_addr = cpu_to_le32((u32)pp->cmd_tbl & 0xffffffff);
#ifdef CONFIG_PHYS_64BIT
pp->cmd_slot->tbl_addr_hi =
cpu_to_le32((u32)(((pp->cmd_tbl) >> 16) >> 16));
#endif
}
#define AHCI_GET_CMD_SLOT(c) ((c) ? ffs(c) : 0)
@ -520,7 +523,7 @@ static int ahci_port_start(struct ahci_probe_ent *probe_ent,
* and its scatter-gather table
*/
pp->cmd_tbl = mem;
debug("cmd_tbl_dma = 0x%x\n", pp->cmd_tbl);
debug("cmd_tbl_dma = 0x%lx\n", pp->cmd_tbl);
mem += AHCI_CMD_TBL_HDR;

View file

@ -8,9 +8,12 @@
#include <common.h>
#include <cpu.h>
#include <dm.h>
#include <errno.h>
#include <dm/lists.h>
#include <dm/root.h>
DECLARE_GLOBAL_DATA_PTR;
int cpu_get_desc(struct udevice *dev, char *buf, int size)
{
struct cpu_ops *ops = cpu_get_ops(dev);
@ -25,12 +28,22 @@ int cpu_get_info(struct udevice *dev, struct cpu_info *info)
{
struct cpu_ops *ops = cpu_get_ops(dev);
if (!ops->get_desc)
if (!ops->get_info)
return -ENOSYS;
return ops->get_info(dev, info);
}
int cpu_get_count(struct udevice *dev)
{
struct cpu_ops *ops = cpu_get_ops(dev);
if (!ops->get_count)
return -ENOSYS;
return ops->get_count(dev);
}
U_BOOT_DRIVER(cpu_bus) = {
.name = "cpu_bus",
.id = UCLASS_SIMPLE_BUS,

View file

@ -1035,7 +1035,7 @@ static void process_nodes(const void *blob, int node_list[], int count,
CONFIG_SYS_I2C_S3C24X0_SPEED);
bus->node = node;
bus->bus_num = i;
exynos_pinmux_config(PERIPH_ID_I2C0 + bus->id, flags);
exynos_pinmux_config(bus->id, flags);
/* Mark position as used */
node_list[i] = -1;

View file

@ -13,7 +13,11 @@
#include <mmc.h>
#include <sdhci.h>
#if defined(CONFIG_FIXED_SDHCI_ALIGNED_BUFFER)
void *aligned_buffer = (void *)CONFIG_FIXED_SDHCI_ALIGNED_BUFFER;
#else
void *aligned_buffer;
#endif
static void sdhci_reset(struct sdhci_host *host, u8 mask)
{
@ -133,8 +137,8 @@ static int sdhci_send_command(struct mmc *mmc, struct mmc_cmd *cmd,
int trans_bytes = 0, is_aligned = 1;
u32 mask, flags, mode;
unsigned int time = 0, start_addr = 0;
unsigned int retry = 10000;
int mmc_dev = mmc->block_dev.dev;
unsigned start = get_timer(0);
/* Timeout unit - ms */
static unsigned int cmd_timeout = CONFIG_SDHCI_CMD_DEFAULT_TIMEOUT;
@ -205,6 +209,17 @@ static int sdhci_send_command(struct mmc *mmc, struct mmc_cmd *cmd,
memcpy(aligned_buffer, data->src, trans_bytes);
}
#if defined(CONFIG_FIXED_SDHCI_ALIGNED_BUFFER)
/*
* Always use this bounce-buffer when
* CONFIG_FIXED_SDHCI_ALIGNED_BUFFER is defined
*/
is_aligned = 0;
start_addr = (unsigned long)aligned_buffer;
if (data->flags != MMC_DATA_READ)
memcpy(aligned_buffer, data->src, trans_bytes);
#endif
sdhci_writel(host, start_addr, SDHCI_DMA_ADDRESS);
mode |= SDHCI_TRNS_DMA;
#endif
@ -222,15 +237,15 @@ static int sdhci_send_command(struct mmc *mmc, struct mmc_cmd *cmd,
flush_cache(start_addr, trans_bytes);
#endif
sdhci_writew(host, SDHCI_MAKE_CMD(cmd->cmdidx, flags), SDHCI_COMMAND);
start = get_timer(0);
do {
stat = sdhci_readl(host, SDHCI_INT_STATUS);
if (stat & SDHCI_INT_ERROR)
break;
if (--retry == 0)
break;
} while ((stat & mask) != mask);
} while (((stat & mask) != mask) &&
(get_timer(start) < CONFIG_SDHCI_CMD_DEFAULT_TIMEOUT));
if (retry == 0) {
if (get_timer(start) >= CONFIG_SDHCI_CMD_DEFAULT_TIMEOUT) {
if (host->quirks & SDHCI_QUIRK_BROKEN_R1B)
return 0;
else {

View file

@ -43,7 +43,7 @@ static int get_part(const char *partname, int *idx, loff_t *off, loff_t *size,
}
int mtd_arg_off(const char *arg, int *idx, loff_t *off, loff_t *size,
loff_t *maxsize, int devtype, int chipsize)
loff_t *maxsize, int devtype, uint64_t chipsize)
{
if (!str2off(arg, off))
return get_part(arg, idx, off, size, maxsize, devtype);
@ -59,7 +59,8 @@ int mtd_arg_off(const char *arg, int *idx, loff_t *off, loff_t *size,
}
int mtd_arg_off_size(int argc, char *const argv[], int *idx, loff_t *off,
loff_t *size, loff_t *maxsize, int devtype, int chipsize)
loff_t *size, loff_t *maxsize, int devtype,
uint64_t chipsize)
{
int ret;

View file

@ -296,6 +296,7 @@ int pci_auto_config_devices(struct udevice *bus)
!ret && dev;
ret = device_find_next_child(&dev)) {
struct pci_child_platdata *pplat;
struct pci_controller *ctlr_hose;
pplat = dev_get_parent_platdata(dev);
unsigned int max_bus;
@ -303,7 +304,10 @@ int pci_auto_config_devices(struct udevice *bus)
bdf = PCI_ADD_BUS(bus->seq, pplat->devfn);
debug("%s: device %s\n", __func__, dev->name);
max_bus = pciauto_config_device(hose, bdf);
/* The root controller has the region information */
ctlr_hose = hose->ctlr->uclass_priv;
max_bus = pciauto_config_device(ctlr_hose, bdf);
sub_bus = max(sub_bus, max_bus);
}
debug("%s: done\n", __func__);
@ -330,7 +334,7 @@ int dm_pci_hose_probe_bus(struct pci_controller *hose, pci_dev_t bdf)
sub_bus = pci_get_bus_max() + 1;
debug("%s: bus = %d/%s\n", __func__, sub_bus, bus->name);
pciauto_prescan_setup_bridge(hose, bdf, bus->seq);
pciauto_prescan_setup_bridge(hose, bdf, sub_bus);
ret = device_probe(bus);
if (ret) {
@ -440,6 +444,7 @@ static int decode_regions(struct pci_controller *hose, const void *blob,
{
int pci_addr_cells, addr_cells, size_cells;
int cells_per_record;
phys_addr_t addr;
const u32 *prop;
int len;
int i;
@ -490,8 +495,11 @@ static int decode_regions(struct pci_controller *hose, const void *blob,
}
/* Add a region for our local memory */
pci_set_region(hose->regions + hose->region_count++, 0, 0,
gd->ram_size, PCI_REGION_MEM | PCI_REGION_SYS_MEMORY);
addr = gd->ram_size;
if (gd->pci_ram_top && gd->pci_ram_top < addr)
addr = gd->pci_ram_top;
pci_set_region(hose->regions + hose->region_count++, 0, 0, addr,
PCI_REGION_MEM | PCI_REGION_SYS_MEMORY);
return 0;
}

View file

@ -87,6 +87,8 @@ void pciauto_setup_device(struct pci_controller *hose,
pci_size_t bar_size;
u16 cmdstat = 0;
int bar, bar_nr = 0;
u8 header_type;
int rom_addr;
#ifndef CONFIG_PCI_ENUM_ONLY
pci_addr_t bar_value;
struct pci_region *bar_res;
@ -182,38 +184,32 @@ void pciauto_setup_device(struct pci_controller *hose,
bar_nr++;
}
/* Configure the expansion ROM address */
pci_hose_read_config_byte(hose, dev, PCI_HEADER_TYPE, &header_type);
if (header_type != PCI_HEADER_TYPE_CARDBUS) {
rom_addr = (header_type == PCI_HEADER_TYPE_NORMAL) ?
PCI_ROM_ADDRESS : PCI_ROM_ADDRESS1;
pci_hose_write_config_dword(hose, dev, rom_addr, 0xfffffffe);
pci_hose_read_config_dword(hose, dev, rom_addr, &bar_response);
if (bar_response) {
bar_size = -(bar_response & ~1);
DEBUGF("PCI Autoconfig: ROM, size=%#x, ", bar_size);
if (pciauto_region_allocate(mem, bar_size,
&bar_value) == 0) {
pci_hose_write_config_dword(hose, dev, rom_addr,
bar_value);
}
cmdstat |= PCI_COMMAND_MEMORY;
DEBUGF("\n");
}
}
pci_hose_write_config_word(hose, dev, PCI_COMMAND, cmdstat);
pci_hose_write_config_byte(hose, dev, PCI_CACHE_LINE_SIZE,
CONFIG_SYS_PCI_CACHE_LINE_SIZE);
pci_hose_write_config_byte(hose, dev, PCI_LATENCY_TIMER, 0x80);
}
int pciauto_setup_rom(struct pci_controller *hose, pci_dev_t dev)
{
pci_addr_t bar_value;
pci_size_t bar_size;
u32 bar_response;
u16 cmdstat = 0;
pci_hose_write_config_dword(hose, dev, PCI_ROM_ADDRESS, 0xfffffffe);
pci_hose_read_config_dword(hose, dev, PCI_ROM_ADDRESS, &bar_response);
if (!bar_response)
return -ENOENT;
bar_size = -(bar_response & ~1);
DEBUGF("PCI Autoconfig: ROM, size=%#x, ", bar_size);
if (pciauto_region_allocate(hose->pci_mem, bar_size, &bar_value) == 0) {
pci_hose_write_config_dword(hose, dev, PCI_ROM_ADDRESS,
bar_value);
}
DEBUGF("\n");
pci_hose_read_config_word(hose, dev, PCI_COMMAND, &cmdstat);
cmdstat |= PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER;
pci_hose_write_config_word(hose, dev, PCI_COMMAND, cmdstat);
return 0;
}
void pciauto_prescan_setup_bridge(struct pci_controller *hose,
pci_dev_t dev, int sub_bus)
{

View file

@ -11,6 +11,7 @@
*/
#include <common.h>
#include <dm.h>
#include <errno.h>
#include <pci.h>
#include <asm/io.h>
@ -221,6 +222,11 @@ phys_addr_t pci_hose_bus_to_phys(struct pci_controller *hose,
return phys_addr;
}
#ifdef CONFIG_DM_PCI
/* The root controller has the region information */
hose = hose->ctlr->uclass_priv;
#endif
/*
* if PCI_REGION_MEM is set we do a two pass search with preference
* on matches that don't have PCI_REGION_SYS_MEMORY set

View file

@ -31,6 +31,7 @@
#include <pci_rom.h>
#include <vbe.h>
#include <video_fb.h>
#include <linux/screen_info.h>
#ifdef CONFIG_HAVE_ACPI_RESUME
#include <asm/acpi.h>
@ -79,15 +80,10 @@ static int pci_rom_probe(pci_dev_t dev, uint class,
if (vendev != mapped_vendev)
debug("Device ID mapped to %#08x\n", mapped_vendev);
#ifdef CONFIG_X86_OPTION_ROM_ADDR
rom_address = CONFIG_X86_OPTION_ROM_ADDR;
#ifdef CONFIG_VGA_BIOS_ADDR
rom_address = CONFIG_VGA_BIOS_ADDR;
#else
if (pciauto_setup_rom(pci_bus_to_hose(PCI_BUS(dev)), dev)) {
debug("Cannot find option ROM\n");
return -ENOENT;
}
pci_read_config_dword(dev, PCI_ROM_ADDRESS, &rom_address);
if (rom_address == 0x00000000 || rom_address == 0xffffffff) {
debug("%s: rom_address=%x\n", __func__, rom_address);
@ -108,6 +104,10 @@ static int pci_rom_probe(pci_dev_t dev, uint class,
if (le16_to_cpu(rom_header->signature) != PCI_ROM_HDR) {
printf("Incorrect expansion ROM header signature %04x\n",
le16_to_cpu(rom_header->signature));
#ifndef CONFIG_VGA_BIOS_ADDR
/* Disable expansion ROM address decoding */
pci_write_config_dword(dev, PCI_ROM_ADDRESS, rom_address);
#endif
return -EINVAL;
}
@ -203,6 +203,7 @@ int vbe_get_video_info(struct graphic_device *gdev)
gdev->gdfBytesPP = vesa->bits_per_pixel / 8;
switch (vesa->bits_per_pixel) {
case 32:
case 24:
gdev->gdfIndex = GDF_32BIT_X888RGB;
break;
@ -229,6 +230,33 @@ int vbe_get_video_info(struct graphic_device *gdev)
#endif
}
void setup_video(struct screen_info *screen_info)
{
#ifdef CONFIG_FRAMEBUFFER_SET_VESA_MODE
struct vesa_mode_info *vesa = &mode_info.vesa;
screen_info->orig_video_isVGA = VIDEO_TYPE_VLFB;
screen_info->lfb_width = vesa->x_resolution;
screen_info->lfb_height = vesa->y_resolution;
screen_info->lfb_depth = vesa->bits_per_pixel;
screen_info->lfb_linelength = vesa->bytes_per_scanline;
screen_info->lfb_base = vesa->phys_base_ptr;
screen_info->lfb_size =
ALIGN(screen_info->lfb_linelength * screen_info->lfb_height,
65536);
screen_info->lfb_size >>= 16;
screen_info->red_size = vesa->red_mask_size;
screen_info->red_pos = vesa->red_mask_pos;
screen_info->green_size = vesa->green_mask_size;
screen_info->green_pos = vesa->green_mask_pos;
screen_info->blue_size = vesa->blue_mask_size;
screen_info->blue_pos = vesa->blue_mask_pos;
screen_info->rsvd_size = vesa->reserved_mask_size;
screen_info->rsvd_pos = vesa->reserved_mask_pos;
#endif
}
int pci_run_vga_bios(pci_dev_t dev, int (*int15_handler)(void), int exec_method)
{
struct pci_rom_header *rom, *ram;

Some files were not shown because too many files have changed in this diff Show more